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;
86 struct street_data *street;
90 struct route_path_segment *path;
91 struct route_path_segment *path_last;
92 struct item_hash *path_hash;
99 struct route_info *pos;
100 struct route_info *dst;
102 struct route_graph *graph;
103 struct route_path *path2;
104 int speedlist[route_item_last-route_item_first+1];
108 struct route_graph_point *route_points;
109 struct route_graph_segment *route_segments;
110 #define HASH_SIZE 8192
111 struct route_graph_point *hash[HASH_SIZE];
114 static struct route_info * route_find_nearest_street(struct mapset *ms, struct coord *c);
115 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
116 static void route_graph_update(struct route *this);
117 static struct route_path *route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst, int *speedlist);
118 static void route_process_street_graph(struct route_graph *this, struct item *item);
119 static void route_graph_destroy(struct route_graph *this);
120 static void route_path_update(struct route *this);
123 route_path_destroy(struct route_path *this)
125 struct route_path_segment *c,*n;
128 if (this->path_hash) {
129 item_hash_destroy(this->path_hash);
130 this->path_hash=NULL;
142 route_new(struct mapset *ms)
144 struct route *this=g_new0(struct route, 1);
150 route_set_mapset(struct route *this, struct mapset *ms)
156 route_get_mapset(struct route *this)
162 route_get_pos(struct route *this)
168 route_get_dst(struct route *this)
174 route_get_speedlist(struct route *this)
176 return this->speedlist;
180 route_set_speed(struct route *this, enum item_type type, int value)
182 if (type < route_item_first || type > route_item_last) {
183 dbg(0,"street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
186 this->speedlist[type-route_item_first]=value;
191 route_contains(struct route *this, struct item *item)
193 if (! this->path2 || !this->path2->path_hash || !item_hash_lookup(this->path2->path_hash, item))
199 route_path_update(struct route *this)
201 route_path_destroy(this->path2);
202 if (! this->pos || ! this->dst)
204 if (! this->graph || !(this->path2=route_path_new(this->graph, this->pos, this->dst, this->speedlist))) {
206 route_graph_update(this);
207 this->path2=route_path_new(this->graph, this->pos, this->dst, this->speedlist);
208 profile(1,"route_path_new");
214 route_set_position(struct route *this, struct coord *pos)
217 route_info_free(this->pos);
218 this->pos=route_find_nearest_street(this->ms, pos);
219 dbg(1,"this->pos=%p\n", this->pos);
223 route_path_update(this);
227 route_set_position_from_tracking(struct route *this, struct tracking *tracking)
230 struct route_info *ret;
233 c=tracking_get_pos(tracking);
234 ret=g_new0(struct route_info, 1);
236 route_info_free(this->pos);
239 ret->pos=tracking_get_segment_pos(tracking);
242 ret->street=street_data_dup(tracking_get_street_data(tracking));
243 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);
244 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);
247 route_path_update(this);
251 struct map_selection *route_selection;
253 struct map_selection *
254 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
256 int dx,dy,sx=1,sy=1,d,m;
257 struct map_selection *sel=g_new(struct map_selection, 1);
258 sel->order[layer_town]=0;
259 sel->order[layer_poly]=0;
260 sel->order[layer_street]=order;
261 dbg(1,"%p %p\n", c1, c2);
266 sel->rect.lu.x=c1->x;
267 sel->rect.rl.x=c2->x;
269 sel->rect.lu.x=c2->x;
270 sel->rect.rl.x=c1->x;
274 sel->rect.lu.y=c2->y;
275 sel->rect.rl.y=c1->y;
277 sel->rect.lu.y=c1->y;
278 sel->rect.rl.y=c2->y;
293 static struct map_selection *
294 route_calc_selection(struct coord *c1, struct coord *c2)
296 struct map_selection *ret,*sel;
297 sel=route_rect(4, c1, c2, 25, 0);
299 sel->next=route_rect(8, c1, c1, 0, 40000);
301 sel->next=route_rect(18, c1, c1, 0, 10000);
303 sel->next=route_rect(8, c2, c2, 0, 40000);
305 sel->next=route_rect(18, c2, c2, 0, 10000);
306 /* route_selection=ret; */
311 route_free_selection(struct map_selection *sel)
313 struct map_selection *next;
324 route_set_destination(struct route *this, struct coord *dst)
328 route_info_free(this->dst);
331 this->dst=route_find_nearest_street(this->ms, dst);
332 profile(1,"find_nearest_street");
334 route_graph_destroy(this->graph);
336 route_path_update(this);
340 static struct route_graph_point *
341 route_graph_get_point(struct route_graph *this, struct coord *c)
343 struct route_graph_point *p=this->route_points;
344 int hashval=(c->x + c->y) & (HASH_SIZE-1);
345 p=this->hash[hashval];
347 if (p->c.x == c->x && p->c.y == c->y)
355 static struct route_graph_point *
356 route_graph_add_point(struct route_graph *this, struct coord *f)
359 struct route_graph_point *p;
361 p=route_graph_get_point(this,f);
363 hashval=(f->x + f->y) & (HASH_SIZE-1);
365 printf("p (0x%x,0x%x)\n", f->x, f->y);
366 p=g_new(struct route_graph_point,1);
367 p->hash_next=this->hash[hashval];
368 this->hash[hashval]=p;
369 p->next=this->route_points;
376 this->route_points=p;
383 route_graph_free_points(struct route_graph *this)
385 struct route_graph_point *curr,*next;
386 curr=this->route_points;
392 this->route_points=NULL;
393 memset(this->hash, 0, sizeof(this->hash));
397 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)
399 struct route_graph_segment *s;
400 s=g_new0(struct route_graph_segment,1);
402 s->start_next=start->start;
405 s->end_next=end->end;
411 s->next=this->route_segments;
412 this->route_segments=s;
414 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
419 route_path_add_item(struct route_path *this, struct item *itm, struct coord *start, struct coord *end, int len, int time)
421 struct route_path_segment *segment=g_new0(struct route_path_segment,1);
422 item_hash_insert(this->path_hash, itm, (void *)1);
428 segment->c[0]=*start;
434 this->path_last->next=segment;
435 this->path_last=segment;
439 struct route_path_handle {
440 struct route_path_segment *s;
443 struct route_path_handle *
444 route_path_open(struct route *this)
446 struct route_path_handle *ret=g_new(struct route_path_handle, 1);
448 ret->s=this->path2->path;
452 struct route_path_segment *
453 route_path_get_segment(struct route_path_handle *h)
455 struct route_path_segment *ret=h->s;
464 route_path_segment_get_start(struct route_path_segment *s)
470 route_path_segment_get_end(struct route_path_segment *s)
476 route_path_segment_get_item(struct route_path_segment *s)
482 route_path_segment_get_length(struct route_path_segment *s)
488 route_path_segment_get_time(struct route_path_segment *s)
494 route_path_close(struct route_path_handle *h)
501 route_graph_free_segments(struct route_graph *this)
503 struct route_graph_segment *curr,*next;
504 curr=this->route_segments;
510 this->route_segments=NULL;
514 route_graph_destroy(struct route_graph *this)
517 route_graph_free_points(this);
518 route_graph_free_segments(this);
524 route_time(int *speedlist, struct item *item, int len)
526 if (item->type < route_item_first || item->type > route_item_last) {
527 dbg(0,"street type %d out of range [%d,%d]", item->type, route_item_first, route_item_last);
530 return len*36/speedlist[item->type-route_item_first];
535 route_value(int *speedlist, struct item *item, int len)
539 printf("len=%d\n", len);
542 ret=route_time(speedlist, item, len);
543 dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret);
548 route_process_street_graph(struct route_graph *this, struct item *item)
555 struct route_graph_point *s_pnt,*e_pnt;
560 if (item_coord_get(item, &l, 1)) {
561 s_pnt=route_graph_add_point(this,&l);
562 while (item_coord_get(item, &c, 1)) {
563 len+=transform_distance(&l, &c);
566 e_pnt=route_graph_add_point(this,&l);
568 if (item_attr_get(item, attr_limit, &attr))
569 route_graph_add_segment(this, s_pnt, e_pnt, len, item, attr.u.num);
571 route_graph_add_segment(this, s_pnt, e_pnt, len, item, 0);
576 compare(void *v1, void *v2)
578 struct route_graph_point *p1=v1;
579 struct route_graph_point *p2=v2;
582 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
584 return p1->value-p2->value;
588 route_info_length(struct route_info *pos, struct route_info *dst, int dir)
590 struct route_info_handle *h;
594 dbg(2,"enter pos=%p dst=%p dir=%d\n", pos, dst, dir);
595 h=route_info_open(pos, dst, dir);
601 while ((c=route_info_get(h))) {
603 ret+=transform_distance(c, l);
606 dbg(2,"ret=%d\n", ret);
611 route_graph_flood(struct route_graph *this, struct route_info *dst, int *speedlist)
613 struct route_graph_point *p_min,*end=NULL;
614 struct route_graph_segment *s;
616 struct fibheap *heap;
617 struct street_data *sd=dst->street;
619 heap = fh_makeheap();
620 fh_setcmp(heap, compare);
622 if (! (sd->limit & 2)) {
623 end=route_graph_get_point(this, &sd->c[0]);
625 end->value=route_value(speedlist, &sd->item, route_info_length(NULL, dst, -1));
626 end->el=fh_insert(heap, end);
629 if (! (sd->limit & 1)) {
630 end=route_graph_get_point(this, &sd->c[sd->count-1]);
632 end->value=route_value(speedlist, &sd->item, route_info_length(NULL, dst, 1));
633 end->el=fh_insert(heap, end);
636 dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y);
638 p_min=fh_extractmin(heap);
643 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);
647 val=route_value(speedlist, &s->item, s->len);
649 val+=val*2*street_route_contained(s->str->segid);
653 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);
654 if (new < s->end->value && !(s->limit & 1)) {
659 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
660 s->end->el=fh_insert(heap, s->end);
662 printf("el new=%p\n", s->end->el);
666 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
667 fh_replacedata(heap, s->end->el, s->end);
676 val=route_value(speedlist, &s->item, s->len);
679 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);
680 if (new < s->start->value && !(s->limit & 2)) {
684 if (! s->start->el) {
686 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
687 s->start->el=fh_insert(heap, s->start);
689 printf("el new=%p\n", s->start->el);
693 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
694 fh_replacedata(heap, s->start->el, s->start);
705 static struct route_path *
706 route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst, int *speedlist)
708 struct route_graph_point *start1=NULL,*start2=NULL,*start;
709 struct route_graph_segment *s=NULL;
711 int ilen,seg_time,seg_len;
713 int time=0,hr,min,sec
715 unsigned int val1=0xffffffff,val2=0xffffffff;
716 struct street_data *sd=pos->street;
717 struct route_path *ret;
719 if (! (sd->limit & 1)) {
720 start1=route_graph_get_point(this, &sd->c[0]);
723 val1=start1->value+route_value(speedlist, &sd->item, route_info_length(pos, NULL, -1));
724 dbg(1,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1);
726 if (! (sd->limit & 2)) {
727 start2=route_graph_get_point(this, &sd->c[sd->count-1]);
730 val2=start2->value+route_value(speedlist, &sd->item, route_info_length(pos, NULL, 1));
731 dbg(1,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2);
733 dbg(1,"val1=%d val2=%d\n", val1, val2);
735 val1=start1->start->start->value;
736 val2=start2->end->end->value;
738 if (start1 && (val1 < val2)) {
746 printf("no route found, pos blocked\n");
750 ret=g_new0(struct route_path, 1);
751 ret->path_hash=item_hash_new();
752 dbg(1,"dir=%d\n", pos->dir);
753 while ((s=start->seg)) {
756 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
759 seg_time=route_time(speedlist, &s->item, seg_len);
764 if (s->start == start) {
765 route_path_add_item(ret, &s->item, &s->start->c, &s->end->c, seg_len, seg_time);
768 route_path_add_item(ret, &s->item, &s->end->c, &s->start->c, seg_len, seg_time);
773 dbg(1,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
774 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);
775 if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y)
777 else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y)
780 printf("no route found\n");
781 route_path_destroy(ret);
784 ilen=route_info_length(pos, NULL, 0);
786 time+=route_time(&pos->street->item, ilen);
790 ilen=route_info_length(NULL, dst, 0);
792 time+=route_time(&dst->street->item, ilen);
796 dbg(1, "%d segments\n", segs);
798 dbg(1, "len %5.3f\n", len/1000.0);
805 dbg(1, "time %02d:%02d:%02d (%d sec)\n", hr, min, time, sec);
806 dbg(1, "speed %f km/h\n", len/sec*3.6);
811 static struct route_graph *
812 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2)
814 struct route_graph *ret=g_new0(struct route_graph, 1);
815 struct map_selection *sel;
816 struct mapset_handle *h;
822 sel=route_calc_selection(c1, c2);
824 while ((m=mapset_next(h,1))) {
825 mr=map_rect_new(m, sel);
826 while ((item=map_rect_get_item(mr))) {
827 if (item->type >= type_street_0 && item->type <= type_ferry) {
828 route_process_street_graph(ret, item);
830 while (item_coord_get(item, &e, 1));
832 map_rect_destroy(mr);
835 route_free_selection(sel);
841 route_graph_update(struct route *this)
843 route_graph_destroy(this->graph);
844 profile(1,"graph_free");
845 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c);
846 profile(1,"route_graph_build");
847 route_graph_flood(this->graph, this->dst, this->speedlist);
848 profile(1,"route_graph_flood");
853 street_get_data (struct item *item)
855 struct coord c[1000];
857 struct street_data *ret;
860 while (count < 1000) {
861 if (!item_coord_get(item, &c[count], 1))
865 g_assert(count < 1000);
866 ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord));
869 if (item_attr_get(item, attr_limit, &attr))
870 ret->limit=attr.u.num;
873 memcpy(ret->c, c, count*sizeof(struct coord));
880 street_data_dup(struct street_data *orig)
882 struct street_data *ret;
883 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
886 memcpy(ret, orig, size);
892 street_data_free(struct street_data *sd)
897 static struct route_info *
898 route_find_nearest_street(struct mapset *ms, struct coord *c)
900 struct route_info *ret=NULL;
902 struct map_selection *sel=route_rect(18, c, c, 0, max_dist);
904 struct mapset_handle *h;
908 struct coord lp, sc[1000];
909 struct street_data *sd;
912 while ((m=mapset_next(h,1))) {
913 mr=map_rect_new(m, sel);
914 while ((item=map_rect_get_item(mr))) {
915 if (item->type >= type_street_0 && item->type <= type_ferry) {
916 sd=street_get_data(item);
917 dist=transform_distance_polyline_sq(sd->c, sd->count, c, &lp, &pos);
918 if (!ret || dist < ret->dist) {
920 street_data_free(ret->street);
923 ret=g_new(struct route_info, 1);
930 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
932 street_data_free(sd);
934 while (item_coord_get(item, &sc[0], 1));
936 map_rect_destroy(mr);
944 route_info_free(struct route_info *inf)
947 street_data_free(inf->street);
955 route_info_street(struct route_info *rinf)
961 route_info_point(struct route_info *rinf, int point)
963 struct street_data *sd=rinf->street;
969 dir=point == 2 ? rinf->dir : -rinf->dir;
971 return &sd->c[sd->count-1];
983 struct route_info_handle {
984 struct route_info *start;
985 struct route_info *curr;
986 struct route_info *end;
995 struct route_info_handle *
996 route_info_open(struct route_info *start, struct route_info *end, int dir)
998 struct route_info_handle *ret=g_new0(struct route_info_handle, 1);
1000 struct route_info *curr;
1001 dbg(2,"enter start=%p end=%p dir=%d\n", start, end, dir);
1010 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) {
1011 dbg(1,"return NULL\n");
1014 printf("trivial start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir);
1015 if (start->pos == end->pos) {
1020 if (start->pos > end->pos) {
1025 if (start->pos < end->pos) {
1030 printf("trivial now start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir);
1031 ret->endpos=end->pos;
1036 dbg(2,"dir=%d\n", dir);
1044 dbg(2,"ret=%p\n",ret);
1049 route_info_get(struct route_info_handle *h)
1054 dbg(1,"iter=%d\n", h->iter);
1070 dbg(1,"h->pos=%d\n", h->pos);
1071 if (h->dir && h->pos >= 0 && h->pos < h->curr->street->count && (h->end == NULL || h->endpos!=h->pos)) {
1072 new=&h->curr->street->c[h->pos];
1093 dbg(1,"new=%p (0x%x,0x%x) last=%p\n", new, new->x, new->y, h->last);
1094 if (h->last && new->x == h->last->x && new->y == h->last->y)
1104 route_info_close(struct route_info_handle *h)
1113 route_draw_route_info(struct route_info *pos, struct route_info *dst, struct transformation *t, struct displaylist *dsp)
1115 struct route_info_handle *h;
1117 struct coord_rect r;
1119 struct point pnt[100];
1125 item.type=type_street_route;
1128 h=route_info_open(pos, dst, 0);
1131 dbg(1, "return 0\n");
1135 dbg(1, "pos=%p pos->dir=%d pos->pos=%d\n", pos, pos->dir, pos->pos);
1136 c=route_info_get(h);
1139 while (c && count < 100) {
1140 dbg(1,"c=%p (0x%x,0x%x)\n", c, c->x, c->y);
1141 transform(t, projection_mg, c, &pnt[count++]);
1142 coord_rect_extend(&r, c);
1143 c=route_info_get(h);
1146 if (count && transform_contains(t, projection_mg, &r))
1147 display_add(dsp, &item, count, pnt, "Route");
1148 route_info_close(h);
1149 dbg(1, "return 1\n");
1154 route_draw(struct route *this, struct transformation *t, struct displaylist *dsp)
1157 if (! this->pos || ! this->dst)
1159 if (! route_draw_route_info(this->pos, this->dst, t, dsp)) {
1160 route_draw_route_info(this->pos, NULL, t, dsp);
1161 route_draw_route_info(NULL, this->dst, t, dsp);
1167 struct route_crossings *
1168 route_crossings_get(struct route *this, struct coord *c)
1170 struct route_point *pnt;
1171 struct route_segment *seg;
1173 struct route_crossings *ret;
1175 pnt=route_graph_get_point(this, c);
1178 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1180 seg=seg->start_next;
1184 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1188 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
1189 ret->count=crossings;