Add:Core:Experimental support for traffic distortions
authormartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Wed, 3 Jun 2009 09:37:43 +0000 (09:37 +0000)
committermartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Wed, 3 Jun 2009 09:37:43 +0000 (09:37 +0000)
git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk/navit@2302 ffa7fe5e-494d-0410-b361-a75ebd5db220

navit/attr_def.h
navit/item_def.h
navit/navit.xml
navit/popup.c
navit/route.c

index 5262bab..8c253d0 100644 (file)
@@ -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              *
index 4579ab7..dec5d24 100644 (file)
@@ -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)
index 00e0ef4..4b22c26 100644 (file)
                 <itemgra item_types="street_nopass,street_0,street_1_city,street_1_land" order="12-18">
                     <text text_size="9"/>
                 </itemgra>
+                <itemgra item_types="traffic_distortion" order="2">
+                    <polyline color="#ff9000" width="2"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="3-5">
+                    <polyline color="#ff9000" width="4"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="6">
+                    <polyline color="#ff9000" width="5"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="7-8">
+                    <polyline color="#ff9000" width="8"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="9-10">
+                    <polyline color="#ff9000" width="10"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="11">
+                    <polyline color="#ff9000" width="14"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="12">
+                    <polyline color="#ff9000" width="16"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="13">
+                    <polyline color="#ff9000" width="26"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="14">
+                    <polyline color="#ff9000" width="32"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="15">
+                    <polyline color="#ff9000" width="34"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="16">
+                    <polyline color="#ff9000" width="66"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="17">
+                    <polyline color="#ff9000" width="134"/>
+                </itemgra>
+                <itemgra item_types="traffic_distortion" order="18">
+                    <polyline color="#ff9000" width="265"/>
+                </itemgra>
             </layer>
             <layer name="polylines">
                 <itemgra item_types="aeroway_taxiway" order="10">
index 1f347c1..d5c09f1 100644 (file)
@@ -61,6 +61,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)
 {
        struct coord c;
@@ -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
index dcc2a70..1fed6aa 100644 (file)
@@ -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
@@ -136,6 +138,16 @@ struct route_graph_segment {
 };
 
 /**
+ * @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
  *
  * This is 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: