From b13dd0c7ed3f264531095d52c36f594c1d58de3d Mon Sep 17 00:00:00 2001 From: martin-s Date: Wed, 3 Jun 2009 09:37:43 +0000 Subject: Add:Core:Experimental support for traffic distortions git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit@2302 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navit/attr_def.h | 1 + navit/item_def.h | 1 + navit/navit.xml | 39 +++++++++++++++ navit/popup.c | 74 +++++++++++++++++++++++---- navit/route.c | 149 ++++++++++++++++++++++++++++++++++++++++++------------- 5 files changed, 220 insertions(+), 44 deletions(-) (limited to 'navit') diff --git a/navit/attr_def.h b/navit/attr_def.h index 5262bab89..8c253d070 100644 --- a/navit/attr_def.h +++ b/navit/attr_def.h @@ -118,6 +118,7 @@ ATTR(flags_reverse_mask) ATTR(house_number_interpolation) ATTR(house_number_left_interpolation) ATTR(house_number_right_interpolation) +ATTR(delay) ATTR2(0x00027500,type_rel_abs_begin) /* These attributes are int that can either hold relative * diff --git a/navit/item_def.h b/navit/item_def.h index 4579ab77c..dec5d24f0 100644 --- a/navit/item_def.h +++ b/navit/item_def.h @@ -423,6 +423,7 @@ ITEM(street_turn_restriction_only) ITEM(border_city) ITEM(border_county) ITEM(selected_line) +ITEM(traffic_distortion) /* Area */ ITEM2(0xc0000000,area) ITEM2(0xc0000001,area_unspecified) diff --git a/navit/navit.xml b/navit/navit.xml index 00e0ef4e9..4b22c2662 100644 --- a/navit/navit.xml +++ b/navit/navit.xml @@ -1194,6 +1194,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/navit/popup.c b/navit/popup.c index 1f347c186..d5c09f129 100644 --- a/navit/popup.c +++ b/navit/popup.c @@ -60,6 +60,44 @@ popup_set_no_passing(struct popup_item *item, void *param) #endif +static void +popup_traffic_distortion(struct item *item, char *attr) +{ + FILE *map=fopen("distortion.txt","a"); + struct coord c; + struct map_rect *mr; + fprintf(map,"type=traffic_distortion %s\n",attr); + mr=map_rect_new(item->map,NULL); + item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo); + while (item_coord_get(item, &c, 1)) { + fprintf(map,"0x%x 0x%x\n",c.x,c.y); + } + fclose(map); +} + +static void +popup_traffic_distortion_blocked(struct item *item) +{ + dbg(0,"item=%p\n",item); + popup_traffic_distortion(item, "maxspeed=0"); +} + +static void +popup_traffic_distortion_speed(struct item *item, int maxspeed) +{ + char buffer[256]; + sprintf(buffer,"maxspeed=%d",maxspeed); + popup_traffic_distortion(item,buffer); +} + +static void +popup_traffic_distortion_delay(struct item *item, int delay) +{ + char buffer[256]; + sprintf(buffer,"delay=%d",delay*600); + popup_traffic_distortion(item,buffer); +} + static void popup_set_destination(struct navit *nav, struct pcoord *pc) { @@ -207,23 +245,23 @@ static void popup_show_item(struct navit *nav, void *popup, struct displayitem *di) { struct map_rect *mr; - void *menu, *menu_map, *menu_item; + void *menu, *menu_map, *menu_item, *menu_dist; char *label; - struct item *item; + struct item *item,*diitem; label=graphics_displayitem_get_label(di); - item=graphics_displayitem_get_item(di); + diitem=graphics_displayitem_get_item(di); if (label) - menu=popup_printf(popup, menu_type_submenu, "%s '%s'", item_to_name(item->type), label); + menu=popup_printf(popup, menu_type_submenu, "%s '%s'", item_to_name(diitem->type), label); else - menu=popup_printf(popup, menu_type_submenu, "%s", item_to_name(item->type)); + menu=popup_printf(popup, menu_type_submenu, "%s", item_to_name(diitem->type)); menu_item=popup_printf(menu, menu_type_submenu, "Item"); - popup_printf(menu_item, menu_type_menu, "type: 0x%x", item->type); - popup_printf(menu_item, menu_type_menu, "id: 0x%x 0x%x", item->id_hi, item->id_lo); - if (item->map) { - mr=map_rect_new(item->map,NULL); - item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo); + popup_printf(menu_item, menu_type_menu, "type: 0x%x", diitem->type); + popup_printf(menu_item, menu_type_menu, "id: 0x%x 0x%x", diitem->id_hi, diitem->id_lo); + if (diitem->map) { + mr=map_rect_new(diitem->map,NULL); + item=map_rect_get_item_byid(mr, diitem->id_hi, diitem->id_lo); dbg(1,"item=%p\n", item); if (item) { popup_show_attrs(item->map, menu_item, item); @@ -246,6 +284,22 @@ popup_show_item(struct navit *nav, void *popup, struct displayitem *di) } else { popup_printf(menu, menu_type_menu, "(No map)"); } + if (diitem && item_get_default_flags(diitem->type)) { + int speeds[]={5,10,20,30,40,50,60,70,80,90,100}; + int delays[]={1,2,3,5,10,15,20,30,45,60,75,90,120,150,180,240,300}; + int i; + menu_dist=popup_printf(menu, menu_type_submenu, "Traffic distortion"); + popup_printf_cb(menu_dist, menu_type_menu, callback_new_1(callback_cast(popup_traffic_distortion_blocked), diitem), "Blocked"); + menu_item=popup_printf(menu_dist, menu_type_submenu,"Max speed"); + for (i = 0 ; i < sizeof(speeds)/sizeof(int); i++) { + popup_printf_cb(menu_item, menu_type_menu, callback_new_2(callback_cast(popup_traffic_distortion_speed), diitem, speeds[i]), "%d km/h",speeds[i]); + } + menu_item=popup_printf(menu_dist, menu_type_submenu,"Delay"); + for (i = 0 ; i < sizeof(delays)/sizeof(int); i++) { + popup_printf_cb(menu_item, menu_type_menu, callback_new_2(callback_cast(popup_traffic_distortion_delay), diitem, delays[i]*600), "%d min",delays[i]); + } + } + } static void diff --git a/navit/route.c b/navit/route.c index dcc2a70ba..1fed6aad5 100644 --- a/navit/route.c +++ b/navit/route.c @@ -94,8 +94,10 @@ struct route_graph_point { * to this point's heap-element */ int value; /**< The cost at which one can reach the destination from this point on */ struct coord c; /**< Coordinates of this point */ + int flags; /**< Flags for this point (eg traffic distortion) */ }; +#define RP_TRAFFIC_DISTORTION 1 /** * @brief A segment in the route graph or path @@ -135,6 +137,16 @@ struct route_graph_segment { struct route_segment_data data; /**< The segment data */ }; +/** + * @brief A traffic distortion + * + * This is distortion in the traffic where you can't drive as fast as usual or have to wait for some time + */ +struct route_traffic_distortion { + int maxspeed; /**< Maximum speed possible in km/h */ + int delay; /**< Delay in tenths of seconds */ +}; + /** * @brief A segment in the route path * @@ -183,12 +195,6 @@ struct route_path { struct item_hash *path_hash; /**< A hashtable of all the items represented by this route's segements */ }; -#define RF_FASTEST (1<<0) -#define RF_SHORTEST (1<<1) -#define RF_AVOIDHW (1<<2) -#define RF_AVOIDPAID (1<<3) -#define RF_LOCKONROAD (1<<4) - /** * @brief A complete route * @@ -939,17 +945,13 @@ route_graph_add_point(struct route_graph *this, struct coord *f) hashval=HASHCOORD(f); if (debug_route) printf("p (0x%x,0x%x)\n", f->x, f->y); - p=g_new(struct route_graph_point,1); + p=g_new0(struct route_graph_point,1); if (!p) { printf("%s:Out of memory\n", __FUNCTION__); return p; } p->hash_next=this->hash[hashval]; this->hash[hashval]=p; - p->el=NULL; - p->start=NULL; - p->end=NULL; - p->seg=NULL; p->value=INT_MAX; p->c=*f; } @@ -1395,22 +1397,58 @@ route_graph_destroy(struct route_graph *this) */ static int -route_time_seg(struct vehicleprofile *profile, struct route_segment_data *over) +route_time_seg(struct vehicleprofile *profile, struct route_segment_data *over, struct route_traffic_distortion *dist) { struct roadprofile *roadprofile=vehicleprofile_get_roadprofile(profile, over->item.type); - int speed; + int speed,maxspeed; if (!roadprofile || !roadprofile->route_weight) return INT_MAX; /* maxspeed_handling: 0=always, 1 only if maxspeed restricts the speed, 2 never */ - if (profile->maxspeed_handling != 2 && (over->flags & AF_SPEED_LIMIT)) { - speed=RSD_MAXSPEED(over); - if (profile->maxspeed_handling == 1 && speed > roadprofile->route_weight) - speed=roadprofile->route_weight; - } else - speed=roadprofile->route_weight; + speed=roadprofile->route_weight; + if (profile->maxspeed_handling != 2) { + if (over->flags & AF_SPEED_LIMIT) { + maxspeed=RSD_MAXSPEED(over); + if (!profile->maxspeed_handling) + speed=maxspeed; + } else + maxspeed=INT_MAX; + if (dist && maxspeed > dist->maxspeed) + maxspeed=dist->maxspeed; + if (maxspeed != INT_MAX && (profile->maxspeed_handling != 1 || maxspeed < speed)) + speed=maxspeed; + } if (!speed) - return INT_MAX; - return over->len*36/speed; + return INT_MAX; + return over->len*36/speed+(dist ? dist->delay : 0); +} + +static int +route_get_traffic_distortion(struct route_graph_segment *seg, struct route_traffic_distortion *ret) +{ + struct route_graph_point *start=seg->start; + struct route_graph_point *end=seg->end; + struct route_graph_segment *tmp,*found=NULL; + tmp=start->start; + while (tmp && !found) { + if (tmp->data.item.type == type_traffic_distortion && tmp->start == start && tmp->end == end) + found=tmp; + tmp=tmp->start_next; + } + tmp=start->end; + while (tmp && !found) { + if (tmp->data.item.type == type_traffic_distortion && tmp->end == start && tmp->start == end) + found=tmp; + tmp=tmp->end_next; + } + if (found) { + ret->delay=found->data.len; + if (found->data.flags & AF_SPEED_LIMIT) + ret->maxspeed=RSD_MAXSPEED(&found->data); + else + ret->maxspeed=INT_MAX; + return 1; + } + return 0; } /** @@ -1424,14 +1462,54 @@ route_time_seg(struct vehicleprofile *profile, struct route_segment_data *over) */ static int -route_value_seg(struct vehicleprofile *profile, struct route_graph_point *from, struct route_segment_data *over, int dir) +route_value_seg(struct vehicleprofile *profile, struct route_graph_point *from, struct route_graph_segment *over, int dir) { #if 0 dbg(0,"flags 0x%x mask 0x%x flags 0x%x\n", over->flags, dir >= 0 ? profile->flags_forward_mask : profile->flags_reverse_mask, profile->flags); #endif - if ((over->flags & (dir >= 0 ? profile->flags_forward_mask : profile->flags_reverse_mask)) != profile->flags) + if ((over->data.flags & (dir >= 0 ? profile->flags_forward_mask : profile->flags_reverse_mask)) != profile->flags) return INT_MAX; - return route_time_seg(profile, over); + if ((over->start->flags & RP_TRAFFIC_DISTORTION) && (over->end->flags & RP_TRAFFIC_DISTORTION)) { + struct route_traffic_distortion dist; + if (route_get_traffic_distortion(over, &dist)) + return route_time_seg(profile, &over->data, &dist); + } + return route_time_seg(profile, &over->data, NULL); +} + +/** + * @brief Adds a route distortion item to the route graph + * + * @param this The route graph to add to + * @param item The item to add + */ +static void +route_process_traffic_distortion(struct route_graph *this, struct item *item) +{ + struct route_graph_point *s_pnt,*e_pnt; + struct coord c,l; + struct attr delay_attr, maxspeed_attr; + int len=0; + int flags = 0; + int offset = 1; + int maxspeed = INT_MAX; + + if (item_coord_get(item, &l, 1)) { + s_pnt=route_graph_add_point(this,&l); + while (item_coord_get(item, &c, 1)) { + l=c; + } + e_pnt=route_graph_add_point(this,&l); + s_pnt->flags |= RP_TRAFFIC_DISTORTION; + e_pnt->flags |= RP_TRAFFIC_DISTORTION; + if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) { + flags |= AF_SPEED_LIMIT; + maxspeed=maxspeed_attr.u.num; + } + if (item_attr_get(item, attr_delay, &delay_attr)) + len=delay_attr.u.num; + route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed); + } } /** @@ -1458,7 +1536,7 @@ route_process_street_graph(struct route_graph *this, struct item *item) int segmented = 0; int offset = 1; int maxspeed = -1; - + if (item_coord_get(item, &l, 1)) { int *default_flags=item_get_default_flags(item->type); if (! default_flags) @@ -1557,14 +1635,14 @@ route_graph_flood(struct route_graph *this, struct route_info *dst, struct vehic dbg(0,"no segment for destination found\n"); return; } - val=route_value_seg(profile, NULL, &s->data, -1); + val=route_value_seg(profile, NULL, s, -1); if (val != INT_MAX) { val=val*(100-dst->percent)/100; s->end->seg=s; s->end->value=val; s->end->el=fh_insertkey(heap, s->end->value, s->end); } - val=route_value_seg(profile, NULL, &s->data, 1); + val=route_value_seg(profile, NULL, s, 1); if (val != INT_MAX) { val=val*dst->percent/100; s->start->seg=s; @@ -1581,7 +1659,7 @@ route_graph_flood(struct route_graph *this, struct route_info *dst, struct vehic p_min->el=NULL; /* This point is permanently calculated now, we've taken it out of the heap */ s=p_min->start; while (s) { /* Iterating all the segments leading away from our point to update the points at their ends */ - val=route_value_seg(profile, p_min, &s->data, -1); + val=route_value_seg(profile, p_min, s, -1); if (val != INT_MAX) { new=min+val; if (debug_route) @@ -1609,7 +1687,7 @@ route_graph_flood(struct route_graph *this, struct route_info *dst, struct vehic } s=p_min->end; while (s) { /* Doing the same as above with the segments leading towards our point */ - val=route_value_seg(profile, p_min, &s->data, 1); + val=route_value_seg(profile, p_min, s, 1); if (val != INT_MAX) { new=min+val; if (debug_route) @@ -1758,12 +1836,12 @@ route_path_new(struct route_graph *this, struct route_path *oldpath, struct rout dbg(0,"no segment for position found\n"); return NULL; } - val=route_value_seg(profile, NULL, &s->data, 1); + val=route_value_seg(profile, NULL, s, 1); if (val != INT_MAX) { val=val*(100-pos->percent)/100; val1=s->end->value+val; } - val=route_value_seg(profile, NULL, &s->data, -1); + val=route_value_seg(profile, NULL, s, -1); if (val != INT_MAX) { val=val*pos->percent/100; val2=s->start->value+val; @@ -1866,7 +1944,10 @@ route_graph_build_idle(struct route_graph *rg) return; } } - route_process_street_graph(rg, item); + if (item->type == type_traffic_distortion) + route_process_traffic_distortion(rg, item); + else + route_process_street_graph(rg, item); count--; } } @@ -2245,7 +2326,7 @@ rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) case attr_time: mr->attr_next=attr_none; if (seg) - attr->u.num=route_time_seg(route->vehicleprofile, seg->data); + attr->u.num=route_time_seg(route->vehicleprofile, seg->data, NULL); else return 0; return 1; @@ -2399,7 +2480,7 @@ rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) case type_rg_segment: if (! seg) return 0; - mr->str=g_strdup_printf("len %d time %d",seg->data.len, route_time_seg(route->vehicleprofile, &seg->data)); + mr->str=g_strdup_printf("len %d time %d",seg->data.len, route_time_seg(route->vehicleprofile, &seg->data, NULL)); attr->u.str = mr->str; return 1; default: -- cgit v1.2.1