14 #include "projection.h"
22 #include "transform.h"
26 static int speed_list[]={
28 10, /* street_1_city */
29 30, /* street_2_city */
30 40, /* street_3_city */
31 50, /* street_4_city */
32 80, /* highway_city */
33 60, /* street_1_land */
34 65, /* street_2_land */
35 70, /* street_3_land */
36 80, /* street_4_land */
37 120, /* street_n_lanes */
38 120, /* highway_land */
47 struct route_graph_point {
48 struct route_graph_point *next;
49 struct route_graph_point *hash_next;
50 struct route_graph_segment *start;
51 struct route_graph_segment *end;
52 struct route_graph_segment *seg;
53 struct fibheap_el *el;
59 struct route_graph_segment {
60 struct route_graph_segment *next;
61 struct route_graph_segment *start_next;
62 struct route_graph_segment *end_next;
63 struct route_graph_point *start;
64 struct route_graph_point *end;
70 struct route_path_segment {
75 struct route_path_segment *next;
94 struct street_data *street;
98 struct route_path_segment *path;
99 struct route_path_segment *path_last;
100 struct item_hash *path_hash;
107 struct route_info *pos;
108 struct route_info *dst;
110 struct route_graph *graph;
111 struct route_path *path2;
112 int speedlist[route_item_last-route_item_first+1];
116 struct route_graph_point *route_points;
117 struct route_graph_segment *route_segments;
118 #define HASH_SIZE 8192
119 struct route_graph_point *hash[HASH_SIZE];
122 static struct route_info * route_find_nearest_street(struct mapset *ms, struct coord *c);
123 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
124 static void route_graph_update(struct route *this);
125 static struct route_path *route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst, int *speedlist);
126 static void route_process_street_graph(struct route_graph *this, struct item *item);
127 static void route_graph_destroy(struct route_graph *this);
128 static void route_path_update(struct route *this);
132 route_path_destroy(struct route_path *this)
134 struct route_path_segment *c,*n;
137 if (this->path_hash) {
138 item_hash_destroy(this->path_hash);
139 this->path_hash=NULL;
151 route_new(struct mapset *ms)
153 struct route *this=g_new0(struct route, 1);
159 route_set_mapset(struct route *this, struct mapset *ms)
165 route_get_mapset(struct route *this)
171 route_get_pos(struct route *this)
177 route_get_dst(struct route *this)
183 route_get_speedlist(struct route *this)
185 return this->speedlist;
189 route_set_speed(struct route *this, enum item_type type, int value)
191 if (type < route_item_first || type > route_item_last) {
192 dbg(0,"street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
195 this->speedlist[type-route_item_first]=value;
200 route_contains(struct route *this, struct item *item)
202 if (! this->path2 || !this->path2->path_hash || !item_hash_lookup(this->path2->path_hash, item))
208 route_path_update(struct route *this)
210 route_path_destroy(this->path2);
211 if (! this->pos || ! this->dst)
213 if (! this->graph || !(this->path2=route_path_new(this->graph, this->pos, this->dst, this->speedlist))) {
215 route_graph_update(this);
216 this->path2=route_path_new(this->graph, this->pos, this->dst, this->speedlist);
217 profile(1,"route_path_new");
223 route_set_position(struct route *this, struct coord *pos)
226 route_info_free(this->pos);
227 this->pos=route_find_nearest_street(this->ms, pos);
228 dbg(1,"this->pos=%p\n", this->pos);
232 route_path_update(this);
236 route_set_position_from_tracking(struct route *this, struct tracking *tracking)
239 struct route_info *ret;
242 c=tracking_get_pos(tracking);
243 ret=g_new0(struct route_info, 1);
245 route_info_free(this->pos);
248 ret->pos=tracking_get_segment_pos(tracking);
251 ret->street=street_data_dup(tracking_get_street_data(tracking));
252 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);
253 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);
256 route_path_update(this);
260 struct map_selection *route_selection;
262 struct map_selection *
263 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
265 int dx,dy,sx=1,sy=1,d,m;
266 struct map_selection *sel=g_new(struct map_selection, 1);
267 sel->order[layer_town]=0;
268 sel->order[layer_poly]=0;
269 sel->order[layer_street]=order;
270 dbg(1,"%p %p\n", c1, c2);
275 sel->rect.lu.x=c1->x;
276 sel->rect.rl.x=c2->x;
278 sel->rect.lu.x=c2->x;
279 sel->rect.rl.x=c1->x;
283 sel->rect.lu.y=c2->y;
284 sel->rect.rl.y=c1->y;
286 sel->rect.lu.y=c1->y;
287 sel->rect.rl.y=c2->y;
302 static struct map_selection *
303 route_calc_selection(struct coord *c1, struct coord *c2)
305 struct map_selection *ret,*sel;
306 sel=route_rect(4, c1, c2, 25, 0);
308 sel->next=route_rect(8, c1, c1, 0, 40000);
310 sel->next=route_rect(18, c1, c1, 0, 10000);
312 sel->next=route_rect(8, c2, c2, 0, 40000);
314 sel->next=route_rect(18, c2, c2, 0, 10000);
315 /* route_selection=ret; */
320 route_free_selection(struct map_selection *sel)
322 struct map_selection *next;
333 route_set_destination(struct route *this, struct coord *dst)
337 route_info_free(this->dst);
340 this->dst=route_find_nearest_street(this->ms, dst);
341 profile(1,"find_nearest_street");
343 route_graph_destroy(this->graph);
345 route_path_update(this);
349 static struct route_graph_point *
350 route_graph_get_point(struct route_graph *this, struct coord *c)
352 struct route_graph_point *p=this->route_points;
353 int hashval=(c->x + c->y) & (HASH_SIZE-1);
354 p=this->hash[hashval];
356 if (p->c.x == c->x && p->c.y == c->y)
364 static struct route_graph_point *
365 route_graph_add_point(struct route_graph *this, struct coord *f)
368 struct route_graph_point *p;
370 p=route_graph_get_point(this,f);
372 hashval=(f->x + f->y) & (HASH_SIZE-1);
374 printf("p (0x%x,0x%x)\n", f->x, f->y);
375 p=g_new(struct route_graph_point,1);
376 p->hash_next=this->hash[hashval];
377 this->hash[hashval]=p;
378 p->next=this->route_points;
385 this->route_points=p;
392 route_graph_free_points(struct route_graph *this)
394 struct route_graph_point *curr,*next;
395 curr=this->route_points;
401 this->route_points=NULL;
402 memset(this->hash, 0, sizeof(this->hash));
406 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)
408 struct route_graph_segment *s;
409 s=g_new0(struct route_graph_segment,1);
411 s->start_next=start->start;
414 s->end_next=end->end;
420 s->next=this->route_segments;
421 this->route_segments=s;
423 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
428 route_path_add_item(struct route_path *this, struct item *itm, struct coord *start, struct coord *end, int len, int time)
430 struct route_path_segment *segment=g_new0(struct route_path_segment,1);
431 item_hash_insert(this->path_hash, itm, (void *)1);
437 segment->c[0]=*start;
443 this->path_last->next=segment;
444 this->path_last=segment;
448 struct route_path_handle {
449 struct route_path_segment *s;
452 struct route_path_handle *
453 route_path_open(struct route *this)
455 struct route_path_handle *ret=g_new(struct route_path_handle, 1);
457 ret->s=this->path2->path;
461 struct route_path_segment *
462 route_path_get_segment(struct route_path_handle *h)
464 struct route_path_segment *ret=h->s;
473 route_path_segment_get_start(struct route_path_segment *s)
479 route_path_segment_get_end(struct route_path_segment *s)
485 route_path_segment_get_item(struct route_path_segment *s)
491 route_path_segment_get_length(struct route_path_segment *s)
497 route_path_segment_get_time(struct route_path_segment *s)
503 route_path_close(struct route_path_handle *h)
510 route_graph_free_segments(struct route_graph *this)
512 struct route_graph_segment *curr,*next;
513 curr=this->route_segments;
519 this->route_segments=NULL;
523 route_graph_destroy(struct route_graph *this)
526 route_graph_free_points(this);
527 route_graph_free_segments(this);
533 route_time(int *speedlist, struct item *item, int len)
535 if (item->type < route_item_first || item->type > route_item_last) {
536 dbg(0,"street type %d out of range [%d,%d]", item->type, route_item_first, route_item_last);
539 return len*36/speedlist[item->type-route_item_first];
544 route_value(int *speedlist, struct item *item, int len)
548 printf("len=%d\n", len);
551 ret=route_time(speedlist, item, len);
552 dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret);
557 route_process_street_graph(struct route_graph *this, struct item *item)
564 struct route_graph_point *s_pnt,*e_pnt;
569 if (item_coord_get(item, &l, 1)) {
570 s_pnt=route_graph_add_point(this,&l);
571 while (item_coord_get(item, &c, 1)) {
572 len+=transform_distance(&l, &c);
575 e_pnt=route_graph_add_point(this,&l);
577 if (item_attr_get(item, attr_limit, &attr))
578 route_graph_add_segment(this, s_pnt, e_pnt, len, item, attr.u.num);
580 route_graph_add_segment(this, s_pnt, e_pnt, len, item, 0);
585 compare(void *v1, void *v2)
587 struct route_graph_point *p1=v1;
588 struct route_graph_point *p2=v2;
591 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
593 return p1->value-p2->value;
597 route_info_length(struct route_info *pos, struct route_info *dst, int dir)
599 struct route_info_handle *h;
603 dbg(2,"enter pos=%p dst=%p dir=%d\n", pos, dst, dir);
604 h=route_info_open(pos, dst, dir);
610 while ((c=route_info_get(h))) {
612 ret+=transform_distance(c, l);
615 dbg(2,"ret=%d\n", ret);
620 route_graph_flood(struct route_graph *this, struct route_info *dst, int *speedlist)
622 struct route_graph_point *p_min,*end=NULL;
623 struct route_graph_segment *s;
625 struct fibheap *heap;
626 struct street_data *sd=dst->street;
628 heap = fh_makeheap();
629 fh_setcmp(heap, compare);
631 if (! (sd->limit & 2)) {
632 end=route_graph_get_point(this, &sd->c[0]);
634 end->value=route_value(speedlist, &sd->item, route_info_length(NULL, dst, -1));
635 end->el=fh_insert(heap, end);
638 if (! (sd->limit & 1)) {
639 end=route_graph_get_point(this, &sd->c[sd->count-1]);
641 end->value=route_value(speedlist, &sd->item, route_info_length(NULL, dst, 1));
642 end->el=fh_insert(heap, end);
645 dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y);
647 p_min=fh_extractmin(heap);
652 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);
656 val=route_value(speedlist, &s->item, s->len);
658 val+=val*2*street_route_contained(s->str->segid);
662 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);
663 if (new < s->end->value && !(s->limit & 1)) {
668 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
669 s->end->el=fh_insert(heap, s->end);
671 printf("el new=%p\n", s->end->el);
675 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
676 fh_replacedata(heap, s->end->el, s->end);
685 val=route_value(speedlist, &s->item, s->len);
688 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);
689 if (new < s->start->value && !(s->limit & 2)) {
693 if (! s->start->el) {
695 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
696 s->start->el=fh_insert(heap, s->start);
698 printf("el new=%p\n", s->start->el);
702 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
703 fh_replacedata(heap, s->start->el, s->start);
714 static struct route_path *
715 route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst, int *speedlist)
717 struct route_graph_point *start1=NULL,*start2=NULL,*start;
718 struct route_graph_segment *s=NULL;
720 int ilen,seg_time,seg_len;
722 int time=0,hr,min,sec
724 unsigned int val1=0xffffffff,val2=0xffffffff;
725 struct street_data *sd=pos->street;
726 struct route_path *ret;
728 if (! (sd->limit & 1)) {
729 start1=route_graph_get_point(this, &sd->c[0]);
732 val1=start1->value+route_value(speedlist, &sd->item, route_info_length(pos, NULL, -1));
733 dbg(1,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1);
735 if (! (sd->limit & 2)) {
736 start2=route_graph_get_point(this, &sd->c[sd->count-1]);
739 val2=start2->value+route_value(speedlist, &sd->item, route_info_length(pos, NULL, 1));
740 dbg(1,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2);
742 dbg(1,"val1=%d val2=%d\n", val1, val2);
744 val1=start1->start->start->value;
745 val2=start2->end->end->value;
747 if (start1 && (val1 < val2)) {
755 printf("no route found, pos blocked\n");
759 ret=g_new0(struct route_path, 1);
760 ret->path_hash=item_hash_new();
761 dbg(1,"dir=%d\n", pos->dir);
762 while ((s=start->seg)) {
765 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
768 seg_time=route_time(speedlist, &s->item, seg_len);
773 if (s->start == start) {
774 route_path_add_item(ret, &s->item, &s->start->c, &s->end->c, seg_len, seg_time);
777 route_path_add_item(ret, &s->item, &s->end->c, &s->start->c, seg_len, seg_time);
782 dbg(1,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
783 dbg(1,"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);
784 if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y)
786 else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y)
789 printf("no route found\n");
790 route_path_destroy(ret);
793 ilen=route_info_length(pos, NULL, 0);
795 time+=route_time(&pos->street->item, ilen);
799 ilen=route_info_length(NULL, dst, 0);
801 time+=route_time(&dst->street->item, ilen);
805 dbg(1, "%d segments\n", segs);
807 dbg(1, "len %5.3f\n", len/1000.0);
814 dbg(1, "time %02d:%02d:%02d (%d sec)\n", hr, min, time, sec);
815 dbg(1, "speed %f km/h\n", len/sec*3.6);
820 static struct route_graph *
821 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2)
823 struct route_graph *ret=g_new0(struct route_graph, 1);
824 struct map_selection *sel;
825 struct mapset_handle *h;
831 sel=route_calc_selection(c1, c2);
833 while ((m=mapset_next(h,1))) {
834 mr=map_rect_new(m, sel);
835 while ((item=map_rect_get_item(mr))) {
836 if (item->type >= type_street_0 && item->type <= type_ferry) {
837 route_process_street_graph(ret, item);
839 while (item_coord_get(item, &e, 1));
841 map_rect_destroy(mr);
844 route_free_selection(sel);
850 route_graph_update(struct route *this)
852 route_graph_destroy(this->graph);
853 profile(1,"graph_free");
854 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c);
855 profile(1,"route_graph_build");
856 route_graph_flood(this->graph, this->dst, this->speedlist);
857 profile(1,"route_graph_flood");
862 street_get_data (struct item *item)
864 struct coord c[1000];
866 struct street_data *ret;
869 while (count < 1000) {
870 if (!item_coord_get(item, &c[count], 1))
874 g_assert(count < 1000);
875 ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord));
878 if (item_attr_get(item, attr_limit, &attr))
879 ret->limit=attr.u.num;
882 memcpy(ret->c, c, count*sizeof(struct coord));
889 street_data_dup(struct street_data *orig)
891 struct street_data *ret;
892 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
895 memcpy(ret, orig, size);
901 street_data_free(struct street_data *sd)
906 static struct route_info *
907 route_find_nearest_street(struct mapset *ms, struct coord *c)
909 struct route_info *ret=NULL;
911 struct map_selection *sel=route_rect(18, c, c, 0, max_dist);
913 struct mapset_handle *h;
917 struct coord lp, sc[1000];
918 struct street_data *sd;
921 while ((m=mapset_next(h,1))) {
922 mr=map_rect_new(m, sel);
923 while ((item=map_rect_get_item(mr))) {
924 if (item->type >= type_street_0 && item->type <= type_ferry) {
925 sd=street_get_data(item);
926 dist=transform_distance_polyline_sq(sd->c, sd->count, c, &lp, &pos);
927 if (!ret || dist < ret->dist) {
929 street_data_free(ret->street);
932 ret=g_new(struct route_info, 1);
939 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
941 street_data_free(sd);
943 while (item_coord_get(item, &sc[0], 1));
945 map_rect_destroy(mr);
953 route_info_free(struct route_info *inf)
956 street_data_free(inf->street);
964 route_info_street(struct route_info *rinf)
970 route_info_point(struct route_info *rinf, int point)
972 struct street_data *sd=rinf->street;
978 dir=point == 2 ? rinf->dir : -rinf->dir;
980 return &sd->c[sd->count-1];
992 struct route_info_handle {
993 struct route_info *start;
994 struct route_info *curr;
995 struct route_info *end;
1004 struct route_info_handle *
1005 route_info_open(struct route_info *start, struct route_info *end, int dir)
1007 struct route_info_handle *ret=g_new0(struct route_info_handle, 1);
1009 struct route_info *curr;
1010 dbg(2,"enter start=%p end=%p dir=%d\n", start, end, dir);
1019 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) {
1020 dbg(1,"return NULL\n");
1023 printf("trivial start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir);
1024 if (start->pos == end->pos) {
1029 if (start->pos > end->pos) {
1034 if (start->pos < end->pos) {
1039 printf("trivial now start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir);
1040 ret->endpos=end->pos;
1045 dbg(2,"dir=%d\n", dir);
1053 dbg(2,"ret=%p\n",ret);
1058 route_info_get(struct route_info_handle *h)
1063 dbg(1,"iter=%d\n", h->iter);
1079 dbg(1,"h->pos=%d\n", h->pos);
1080 if (h->dir && h->pos >= 0 && h->pos < h->curr->street->count && (h->end == NULL || h->endpos!=h->pos)) {
1081 new=&h->curr->street->c[h->pos];
1102 dbg(1,"new=%p (0x%x,0x%x) last=%p\n", new, new->x, new->y, h->last);
1103 if (h->last && new->x == h->last->x && new->y == h->last->y)
1113 route_info_close(struct route_info_handle *h)
1122 route_draw_route_info(struct route_info *pos, struct route_info *dst, struct transformation *t, struct displaylist *dsp)
1124 struct route_info_handle *h;
1126 struct coord_rect r;
1128 struct point pnt[100];
1134 item.type=type_street_route;
1137 h=route_info_open(pos, dst, 0);
1140 dbg(1, "return 0\n");
1144 dbg(1, "pos=%p pos->dir=%d pos->pos=%d\n", pos, pos->dir, pos->pos);
1145 c=route_info_get(h);
1148 while (c && count < 100) {
1149 dbg(1,"c=%p (0x%x,0x%x)\n", c, c->x, c->y);
1150 transform(t, projection_mg, c, &pnt[count++]);
1151 coord_rect_extend(&r, c);
1152 c=route_info_get(h);
1155 if (count && transform_contains(t, projection_mg, &r))
1156 display_add(dsp, &item, count, pnt, "Route");
1157 route_info_close(h);
1158 dbg(1, "return 1\n");
1163 route_draw(struct route *this, struct transformation *t, struct displaylist *dsp)
1166 if (! this->pos || ! this->dst)
1168 if (! route_draw_route_info(this->pos, this->dst, t, dsp)) {
1169 route_draw_route_info(this->pos, NULL, t, dsp);
1170 route_draw_route_info(NULL, this->dst, t, dsp);
1176 struct route_crossings *
1177 route_crossings_get(struct route *this, struct coord *c)
1179 struct route_point *pnt;
1180 struct route_segment *seg;
1182 struct route_crossings *ret;
1184 pnt=route_graph_get_point(this, c);
1187 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1189 seg=seg->start_next;
1193 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1197 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
1198 ret->count=crossings;