From c0b1eaba7515b91d62d2a8f9ff28be956c39dd61 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Sun, 23 Dec 2018 15:09:17 +0100 Subject: Refactor:core:Document transform_distance() Signed-off-by: mvglasow --- navit/transform.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/navit/transform.c b/navit/transform.c index 85a9c41da..4c0cb68b1 100644 --- a/navit/transform.c +++ b/navit/transform.c @@ -993,6 +993,15 @@ int transform_int_scale(int y) { } #endif +/** + * @brief Calculates the distance between two points. + * + * @param pro The projection used for `c1` and `c2`. + * @param c1 The first point. + * @param c2 The second point. + * + * @return The distance in meters. + */ double transform_distance(enum projection pro, struct coord *c1, struct coord *c2) { if (pro == projection_mg) { #ifndef AVOID_FLOAT -- cgit v1.2.1 From 4e43092c25affda136225a32d7eab2e4f6bbedf4 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Sun, 23 Dec 2018 15:20:34 +0100 Subject: Refactor:traffic:Split penalties for off-road links and data mismatch Signed-off-by: mvglasow --- navit/traffic.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/navit/traffic.c b/navit/traffic.c index 4fafa104d..8aa5e4474 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -64,6 +64,9 @@ /** The penalty applied to an off-road link */ #define PENALTY_OFFROAD 4 +/** The penalty applied to segments with non-matching attributes */ +#define PENALTY_SEGMENT_MATCH 4 + /** The maximum penalty applied to points with non-matching attributes */ #define PENALTY_POINT_MATCH 16 @@ -1451,8 +1454,8 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, * * The cost is calculated based on the length of the segment and a penalty which depends on the score. * A segment with the maximum score of 100 is not penalized, i.e. its cost is equal to its length. A - * segment with a zero score is penalized with a factor of `PENALTY_OFFROAD`. For scores in between, a - * penalty factor between 1 and `PENALTY_OFFROAD` is applied. + * segment with a zero score is penalized with a factor of `PENALTY_SEGMENT_MATCH`. For scores in between, a + * penalty factor between 1 and `PENALTY_SEGMENT_MATCH` is applied. * * If the segment is impassable in the given direction, the cost is always `INT_MAX`. * @@ -1471,7 +1474,7 @@ static int traffic_route_get_seg_cost(struct route_graph_segment *over, int dir) if ((over->data.item.type < route_item_first) || (over->data.item.type > route_item_last)) return INT_MAX; - return over->data.len * (100 - over->data.score) * (PENALTY_OFFROAD - 1) / 100 + over->data.len; + return over->data.len * (100 - over->data.score) * (PENALTY_SEGMENT_MATCH - 1) / 100 + over->data.len; } /** -- cgit v1.2.1 From 19c1c3b9d27ba3fd7e4f6ec06930294c6e944a3b Mon Sep 17 00:00:00 2001 From: mvglasow Date: Sun, 23 Dec 2018 18:45:00 +0100 Subject: Fix:traffic:Fix attribute name for road class Signed-off-by: mvglasow --- navit/traffic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/navit/traffic.c b/navit/traffic.c index 8aa5e4474..dd94dcb4f 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -3548,7 +3548,7 @@ static void traffic_dump_messages_to_xml(struct traffic * this_) { if (message->location->ramps) fprintf(f, " ramps=\"%s\"", location_ramps_to_string(message->location->ramps)); if (message->location->road_type != type_line_unspecified) - fprintf(f, " road_type=\"%s\"", item_to_name(message->location->road_type)); + fprintf(f, " road_class=\"%s\"", item_to_name(message->location->road_type)); if (message->location->road_ref) fprintf(f, " road_ref=\"%s\"", message->location->road_ref); if (message->location->road_name) @@ -4182,7 +4182,7 @@ static void traffic_xml_end(xml_context *dummy, const char *tag_name, void *data location_dir_new(traffic_xml_get_attr("directionality", el->names, el->values)), location_fuzziness_new(traffic_xml_get_attr("fuzziness", el->names, el->values)), location_ramps_new(traffic_xml_get_attr("ramps", el->names, el->values)), - item_type_from_road_type(traffic_xml_get_attr("road_type", el->names, el->values), + item_type_from_road_type(traffic_xml_get_attr("road_class", el->names, el->values), /* TODO revisit default for road_is_urban */ boolean_new(traffic_xml_get_attr("road_is_urban", el->names, el->values), 0)), traffic_xml_get_attr("road_name", el->names, el->values), -- cgit v1.2.1 From 54fe67d6a39fe0451b4fdccac9f5af431a8f74d8 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Sun, 23 Dec 2018 18:48:02 +0100 Subject: Fix:traffic:Add default access flags based on road class Signed-off-by: mvglasow --- navit/traffic.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/navit/traffic.c b/navit/traffic.c index dd94dcb4f..fdbc94afe 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -3385,8 +3385,12 @@ static struct seg_data * traffic_message_parse_events(struct traffic_message * t } /* if no vehicle type is specified in supplementary information, assume all */ - if (!has_flags) - flags = AF_ALL; + if (!has_flags) { + if (this_->location->road_type == type_line_unspecified) + flags = AF_ALL; + else + flags = AF_MOTORIZED_FAST | AF_MOPED; + } if (!ret) ret = seg_data_new(); -- cgit v1.2.1 From 36a3a935e78021e54dd61d66f63c2d984e08a81d Mon Sep 17 00:00:00 2001 From: mvglasow Date: Sun, 23 Dec 2018 18:49:54 +0100 Subject: Fix:traffic:Honor access flags wen matching segments Signed-off-by: mvglasow --- navit/traffic.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/navit/traffic.c b/navit/traffic.c index fdbc94afe..739f529d0 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -278,7 +278,7 @@ static struct traffic * traffic_new(struct attr *parent, struct attr **attrs); static int traffic_process_messages_int(struct traffic * this_, int flags); static void traffic_message_dump_to_stderr(struct traffic_message * this_); static struct seg_data * traffic_message_parse_events(struct traffic_message * this_); -static struct route_graph_point * traffic_route_flood_graph(struct route_graph * rg, +static struct route_graph_point * traffic_route_flood_graph(struct route_graph * rg, struct seg_data * data, struct coord * c_start, struct coord * c_dst, struct route_graph_point * start_existing); static struct item_methods methods_traffic_item = { @@ -1460,11 +1460,12 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, * If the segment is impassable in the given direction, the cost is always `INT_MAX`. * * @param over The segment + * @param data Data for the segments added to the map * @param dir The direction (positive numbers indicate positive direction) * * @return The cost of the segment */ -static int traffic_route_get_seg_cost(struct route_graph_segment *over, int dir) { +static int traffic_route_get_seg_cost(struct route_graph_segment *over, struct seg_data * data, int dir) { if (over->data.flags & (dir >= 0 ? AF_ONEWAYREV : AF_ONEWAY)) return INT_MAX; if (dir > 0 && (over->start->flags & RP_TURN_RESTRICTION)) @@ -1473,6 +1474,9 @@ static int traffic_route_get_seg_cost(struct route_graph_segment *over, int dir) return INT_MAX; if ((over->data.item.type < route_item_first) || (over->data.item.type > route_item_last)) return INT_MAX; + /* at least a partial match is required for access flags */ + if (!(over->data.flags & data->flags & AF_ALL)) + return INT_MAX; return over->data.len * (100 - over->data.score) * (PENALTY_SEGMENT_MATCH - 1) / 100 + over->data.len; } @@ -1889,13 +1893,14 @@ static int traffic_location_equals(struct traffic_location * l, struct traffic_l * longer needed. * * @param rg The route graph + * @param data Data for the segments added to the map * @param c_start Start coordinates * @param c_dst Destination coordinates * @param start_existing Start point of an existing route (whose points will not be used) * * @return The point in the route graph at which the path begins, or `NULL` if no path was found. */ -static struct route_graph_point * traffic_route_flood_graph(struct route_graph * rg, +static struct route_graph_point * traffic_route_flood_graph(struct route_graph * rg, struct seg_data * data, struct coord * c_start, struct coord * c_dst, struct route_graph_point * start_existing) { struct route_graph_point * ret; @@ -1976,7 +1981,7 @@ static struct route_graph_point * traffic_route_flood_graph(struct route_graph * p->el = NULL; /* This point is permanently calculated now, we've taken it out of the heap */ s = p->start; while (s) { /* Iterating all the segments leading away from our point to update the points at their ends */ - val = traffic_route_get_seg_cost(s, -1); + val = traffic_route_get_seg_cost(s, data, -1); dbg(lvl_debug, " negative segment, val=%d", val); @@ -2001,7 +2006,7 @@ static struct route_graph_point * traffic_route_flood_graph(struct route_graph * } s = p->end; while (s) { /* Doing the same as above with the segments leading towards our point */ - val = traffic_route_get_seg_cost(s, 1); + val = traffic_route_get_seg_cost(s, data, 1); dbg(lvl_debug, " positive segment, val=%d", val); @@ -2615,11 +2620,11 @@ static int traffic_message_add_segments(struct traffic_message * this_, struct m dbg(lvl_debug, "*****checkpoint ADD-4.1"); if (point_pairs == 1) { if (dir > 0) - p_start = traffic_route_flood_graph(rg, + p_start = traffic_route_flood_graph(rg, data, pcoords[0] ? pcoords[0] : pcoords[1], pcoords[2] ? pcoords[2] : pcoords[1], NULL); else - p_start = traffic_route_flood_graph(rg, + p_start = traffic_route_flood_graph(rg, data, pcoords[2] ? pcoords[2] : pcoords[1], pcoords[0] ? pcoords[0] : pcoords[1], NULL); dbg(lvl_debug, "*****checkpoint ADD-4.1.1"); @@ -2638,9 +2643,9 @@ static int traffic_message_add_segments(struct traffic_message * this_, struct m /* TODO handle cases in which the route goes through the "third" point * (this should not happen; if it does, we need to detect and fix it) */ if (dir > 0) - p_start = traffic_route_flood_graph(rg, pcoords[0], pcoords[1], NULL); + p_start = traffic_route_flood_graph(rg, data, pcoords[0], pcoords[1], NULL); else - p_start = traffic_route_flood_graph(rg, pcoords[2], pcoords[1], NULL); + p_start = traffic_route_flood_graph(rg, data, pcoords[2], pcoords[1], NULL); if ((this_->location->fuzziness == location_fuzziness_low_res) || this_->location->at || this_->location->not_via) { /* extend start to next junction */ @@ -2651,17 +2656,17 @@ static int traffic_message_add_segments(struct traffic_message * this_, struct m if (dir > 0) { if (!p_start) { /* fallback if calculating the first piece of the route failed */ - p_start = traffic_route_flood_graph(rg, pcoords[1], pcoords[2], NULL); + p_start = traffic_route_flood_graph(rg, data, pcoords[1], pcoords[2], NULL); start_new = traffic_route_prepend(rg, p_start); } else - traffic_route_flood_graph(rg, pcoords[1], pcoords[2], p_start); + traffic_route_flood_graph(rg, data, pcoords[1], pcoords[2], p_start); } else { if (!p_start) { /* fallback if calculating the first piece of the route failed */ - p_start = traffic_route_flood_graph(rg, pcoords[1], pcoords[0], NULL); + p_start = traffic_route_flood_graph(rg, data, pcoords[1], pcoords[0], NULL); start_new = traffic_route_prepend(rg, p_start); } else - traffic_route_flood_graph(rg, pcoords[1], pcoords[0], p_start); + traffic_route_flood_graph(rg, data, pcoords[1], pcoords[0], p_start); } dbg(lvl_debug, "*****checkpoint ADD-4.1.2"); } -- cgit v1.2.1 From b3c49fa1dcf0b873f9c307c996f37107a38ff640 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Tue, 25 Dec 2018 23:27:47 +0100 Subject: Fix:traffic:Increase off-road penalty for segment matching Improves match quality on mountain pass roads Signed-off-by: mvglasow --- navit/traffic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/navit/traffic.c b/navit/traffic.c index 739f529d0..aa0120ca5 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -62,7 +62,7 @@ #define MESSAGE_UPDATE_SEGMENTS 1 << 1 /** The penalty applied to an off-road link */ -#define PENALTY_OFFROAD 4 +#define PENALTY_OFFROAD 8 /** The penalty applied to segments with non-matching attributes */ #define PENALTY_SEGMENT_MATCH 4 -- cgit v1.2.1 From da8efab480e9382e40aadb63076570d147ae2d58 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Mon, 7 Jan 2019 18:29:16 +0100 Subject: Refactor:traffic:Refine debug output Signed-off-by: mvglasow --- navit/traffic.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/navit/traffic.c b/navit/traffic.c index aa0120ca5..da77a8659 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -1359,9 +1359,11 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, /* The attribute being examined */ struct attr attr; - if (!this_->junction_name) + if (!this_->junction_name) { /* nothing to compare, score is 0 */ + dbg(lvl_debug, "p=%p: no junction name, score 0", p); return 0; + } /* find predecessor of p, if any */ while (p_iter && (p_iter != p)) { @@ -1378,6 +1380,7 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, if (!p_prev && (p != start)) { /* not a point on the route */ + dbg(lvl_debug, "p=%p: not on the route, score 0", p); return 0; } /* check if we have a match for the start of a route segment */ @@ -1404,6 +1407,7 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, /* we cannot have multiple matches in different categories */ if (has_start_match && has_end_match) { + dbg(lvl_debug, "p=%p: both start and end match, score 0", p); return 0; } @@ -1434,18 +1438,24 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, map_rect_destroy(mr); } + dbg(lvl_debug, "p=%p: has_offroute_match=%d, has_start_match=%d, has_end_match=%d", + p, has_offroute_match, has_start_match, has_end_match); + if (has_offroute_match) { if (has_start_match || has_end_match) { /* we cannot have multiple matches in different categories */ + dbg(lvl_debug, "p=%p: both off-route and start/end match, score 0", p); return 0; } } else { if ((match_start && !has_start_match) || (!match_start && !has_end_match)) { /* no match in requested category */ + dbg(lvl_debug, "p=%p: no match in requested category, score 0", p); return 0; } } + dbg(lvl_debug, "p=%p: score 100 (full score)", p); return 100; } @@ -2718,7 +2728,11 @@ static int traffic_message_add_segments(struct traffic_message * this_, struct m p_to = NULL; dbg(lvl_debug, "*****checkpoint ADD-4.2.3"); + struct coord_geo wgs; while (p_iter) { + transform_to_geo(projection_mg, &(p_iter->c), &wgs); + dbg(lvl_debug, "*****checkpoint ADD-4.2.3, p_iter=%p (value=%d)\nhttps://www.openstreetmap.org?mlat=%f&mlon=%f/#map=13", + p_iter, p_iter->value, wgs.lat, wgs.lng); if (route_graph_point_is_endpoint_candidate(p_iter, s_prev)) { score = traffic_location_get_point_match(this_->location, p_iter, this_->location->at ? 1 : (dir > 0) ? 2 : 0, @@ -2764,7 +2778,6 @@ static int traffic_message_add_segments(struct traffic_message * this_, struct m minval = INT_MAX; p_from = NULL; - struct coord_geo wgs; transform_to_geo(projection_mg, &(p_start->c), &wgs); dbg(lvl_debug, "*****checkpoint ADD-4.2.6, p_start=%p\nhttps://www.openstreetmap.org?mlat=%f&mlon=%f/#map=13", p_start, wgs.lat, wgs.lng); -- cgit v1.2.1 From 9ec874a084356973cfd760f2d9cf1875b1f79a53 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Mon, 7 Jan 2019 18:29:44 +0100 Subject: Refactor:traffic:Refine comments Signed-off-by: mvglasow --- navit/traffic.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/navit/traffic.c b/navit/traffic.c index da77a8659..084700519 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -1326,6 +1326,10 @@ static int traffic_point_match_attributes(struct traffic_point * this_, struct i * route, only the first point (whose `seg` member points to the segment) will match; the opposite is true when the end * point of the route is evaluated. This ensures the matched segment ends up being part of the route. * + * FIXME this behavior works well if `this_` refers to a point which is actually a segment (such as a bridge or tunnel, + * which we want included in the route), but not if it refers to the crossing road at an intersection (which we want to + * exclude from the route). We need a clear distinction for both cases. + * * If no points can be attained (because no attributes which must match are supplied), the score is 0 for any point. * * @param this_ The traffic point @@ -1344,7 +1348,10 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, /* The predecessor pf `p`in the route graph */ struct route_graph_point *p_prev = NULL; - /* Whether we have a match for the start of a route segment, the end of a route segment or an off-route segment */ + /* + * Whether this_ matches the route segment starting at p (leading away from it), the route segment ending at p + * (leading towards it), or an off-route segment connected to p, respectively + */ int has_start_match = 0, has_end_match = 0, has_offroute_match = 0; /* The route segment being examined */ -- cgit v1.2.1 From 8dce7363b9f9840dc8660696294e0c102f4ee32b Mon Sep 17 00:00:00 2001 From: mvglasow Date: Mon, 7 Jan 2019 18:36:38 +0100 Subject: Refactor:traffic:Internal variable for point attribute matching Signed-off-by: mvglasow --- navit/traffic.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/navit/traffic.c b/navit/traffic.c index 084700519..ffd8cc788 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -1342,6 +1342,12 @@ static int traffic_point_match_attributes(struct traffic_point * this_, struct i static int traffic_point_match_segment_attributes(struct traffic_point * this_, struct route_graph_point *p, struct route_graph_point * start, int match_start) { + /* + * Whether we want a match for the route segment starting at p (leading away from it) or the route segment ending + * at p (leading towards it). + */ + int want_start_match = match_start; + /* Iterator for route graph points */ struct route_graph_point *p_iter = start; @@ -1455,7 +1461,7 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, return 0; } } else { - if ((match_start && !has_start_match) || (!match_start && !has_end_match)) { + if ((want_start_match && !has_start_match) || (!want_start_match && !has_end_match)) { /* no match in requested category */ dbg(lvl_debug, "p=%p: no match in requested category, score 0", p); return 0; -- cgit v1.2.1 From 46738888e3b4411cb2838681d2507f516d6233cf Mon Sep 17 00:00:00 2001 From: mvglasow Date: Mon, 7 Jan 2019 19:01:16 +0100 Subject: Refactor:traffic:Break up some if statements Signed-off-by: mvglasow --- navit/traffic.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/navit/traffic.c b/navit/traffic.c index ffd8cc788..1644e4e73 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -1399,22 +1399,26 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, /* check if we have a match for the start of a route segment */ if (p->seg) { mr = map_rect_new(p->seg->data.item.map, NULL); - if ((item = map_rect_get_item_byid(mr, p->seg->data.item.id_hi, p->seg->data.item.id_lo)) - && item_attr_get(item, attr_street_name, &attr) + if ((item = map_rect_get_item_byid(mr, p->seg->data.item.id_hi, p->seg->data.item.id_lo))) { + if (item_attr_get(item, attr_street_name, &attr)) { // TODO crude comparison in need of refinement - && !strcmp(this_->junction_name, attr.u.str)) - has_start_match = 1; + if (!strcmp(this_->junction_name, attr.u.str)) + has_start_match = 1; + } + } map_rect_destroy(mr); } /* check if we have a match for the end of a route segment */ if (p_prev && p_prev->seg) { mr = map_rect_new(p_prev->seg->data.item.map, NULL); - if ((item = map_rect_get_item_byid(mr, p_prev->seg->data.item.id_hi, p_prev->seg->data.item.id_lo)) - && item_attr_get(item, attr_street_name, &attr) + if ((item = map_rect_get_item_byid(mr, p_prev->seg->data.item.id_hi, p_prev->seg->data.item.id_lo))) { + if (item_attr_get(item, attr_street_name, &attr)) { // TODO crude comparison in need of refinement - && !strcmp(this_->junction_name, attr.u.str)) - has_end_match = 1; + if (!strcmp(this_->junction_name, attr.u.str)) + has_end_match = 1; + } + } map_rect_destroy(mr); } @@ -1430,11 +1434,13 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, /* segments is on the route, skip */ continue; mr = map_rect_new(s->data.item.map, NULL); - if ((item = map_rect_get_item_byid(mr, s->data.item.id_hi, s->data.item.id_lo)) - && item_attr_get(item, attr_street_name, &attr) + if ((item = map_rect_get_item_byid(mr, s->data.item.id_hi, s->data.item.id_lo))) { + if (item_attr_get(item, attr_street_name, &attr)) { // TODO crude comparison in need of refinement - && !strcmp(this_->junction_name, attr.u.str)) - has_offroute_match = 1; + if (!strcmp(this_->junction_name, attr.u.str)) + has_offroute_match = 1; + } + } map_rect_destroy(mr); } @@ -1443,11 +1449,13 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, /* segments is on the route, skip */ continue; mr = map_rect_new(s->data.item.map, NULL); - if ((item = map_rect_get_item_byid(mr, s->data.item.id_hi, s->data.item.id_lo)) - && item_attr_get(item, attr_street_name, &attr) + if ((item = map_rect_get_item_byid(mr, s->data.item.id_hi, s->data.item.id_lo))) { + if (item_attr_get(item, attr_street_name, &attr)) { // TODO crude comparison in need of refinement - && !strcmp(this_->junction_name, attr.u.str)) - has_offroute_match = 1; + if (!strcmp(this_->junction_name, attr.u.str)) + has_offroute_match = 1; + } + } map_rect_destroy(mr); } -- cgit v1.2.1 From 69cd5e85c0804c26704a6e06e6ea97e89774871f Mon Sep 17 00:00:00 2001 From: mvglasow Date: Mon, 7 Jan 2019 20:52:58 +0100 Subject: Fix:traffic:correctly match urban dual-carriageway roads Crossing roads should not be part of the route Signed-off-by: mvglasow --- navit/traffic.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/navit/traffic.c b/navit/traffic.c index 1644e4e73..77417e4a7 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -1322,13 +1322,19 @@ static int traffic_point_match_attributes(struct traffic_point * this_, struct i * the quality of the match. * * Segments which are part of the route are treated in a different manner, as the direction in which the segment is - * traversed (not the direction of the segment itself) is taken into account: When evaluating the start point of the - * route, only the first point (whose `seg` member points to the segment) will match; the opposite is true when the end - * point of the route is evaluated. This ensures the matched segment ends up being part of the route. + * traversed (not the direction of the segment itself) is taken into account, which is needed to govern whether the + * matched segment ends up being part of the route or not. * - * FIXME this behavior works well if `this_` refers to a point which is actually a segment (such as a bridge or tunnel, - * which we want included in the route), but not if it refers to the crossing road at an intersection (which we want to - * exclude from the route). We need a clear distinction for both cases. + * In some cases, `this_` refers to a point which is actually a segment (such as a bridge or tunnel), which we want to + * include in the route. In other cases, `this_` refers to an intersection with another road, and the junction name is + * the name of the other road; these segments need to be excluded from the route. + * + * This is controlled by the `match_start` argument: if true, we are evaluating the start point of a route, else we are + * evaluating its end point. To include the matched segment in the route, only the first point (whose `seg` member + * points to the segment) will match for the start point, the opposite is true for the end point. To exclude the + * matched segment, this logic is reversed. + * + * A heuristic is in place to distinguish whether or not we want the matched segment included. * * If no points can be attained (because no attributes which must match are supplied), the score is 0 for any point. * @@ -1372,6 +1378,12 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, /* The attribute being examined */ struct attr attr; + /* Name and systematic name for route segments starting and ending at p */ + char *start_name = NULL, *start_ref = NULL, *end_name = NULL, *end_ref = NULL; + + /* Whether or not the route follows the road (if both are true or both are false, the case is not clear) */ + int route_follows_road = 0, route_leaves_road = 0; + if (!this_->junction_name) { /* nothing to compare, score is 0 */ dbg(lvl_debug, "p=%p: no junction name, score 0", p); @@ -1401,10 +1413,13 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, mr = map_rect_new(p->seg->data.item.map, NULL); if ((item = map_rect_get_item_byid(mr, p->seg->data.item.id_hi, p->seg->data.item.id_lo))) { if (item_attr_get(item, attr_street_name, &attr)) { + start_name = g_strdup(attr.u.str); // TODO crude comparison in need of refinement if (!strcmp(this_->junction_name, attr.u.str)) has_start_match = 1; } + if (item_attr_get(item, attr_street_name_systematic, &attr)) + start_ref = g_strdup(attr.u.str); } map_rect_destroy(mr); } @@ -1414,22 +1429,42 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, mr = map_rect_new(p_prev->seg->data.item.map, NULL); if ((item = map_rect_get_item_byid(mr, p_prev->seg->data.item.id_hi, p_prev->seg->data.item.id_lo))) { if (item_attr_get(item, attr_street_name, &attr)) { + end_name = g_strdup(attr.u.str); // TODO crude comparison in need of refinement if (!strcmp(this_->junction_name, attr.u.str)) has_end_match = 1; } + if (item_attr_get(item, attr_street_name_systematic, &attr)) + end_ref = g_strdup(attr.u.str); } map_rect_destroy(mr); } - /* we cannot have multiple matches in different categories */ + /* + * If we have both a start match and an end match, the point is in the middle of a stretch of road which matches + * the junction name. Regardless of whether we want that stretch included in the route or not, a middle point + * cannot be an end point. + */ if (has_start_match && has_end_match) { dbg(lvl_debug, "p=%p: both start and end match, score 0", p); + g_free(start_name); + g_free(start_ref); + g_free(end_name); + g_free(end_ref); return 0; } + if (start_name && end_name) + // TODO crude comparison in need of refinement + route_follows_road |= !strcmp(start_name, end_name); + + if (start_ref && end_ref) + // TODO crude comparison in need of refinement + route_follows_road |= !strcmp(start_ref, end_ref); + /* check if we have a match for an off-route segment */ - for (s = p->start; s && !has_offroute_match; s = s->start_next) { + /* TODO consolidate these two loops, which differ only in their loop statement while the body is identical */ + for (s = p->start; s && !(has_offroute_match && route_leaves_road); s = s->start_next) { if ((p->seg == s) || (p_prev && (p_prev->seg == s))) /* segments is on the route, skip */ continue; @@ -1439,12 +1474,23 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, // TODO crude comparison in need of refinement if (!strcmp(this_->junction_name, attr.u.str)) has_offroute_match = 1; + if (start_name) + route_leaves_road |= !strcmp(start_name, attr.u.str); + if (end_name) + route_leaves_road |= !strcmp(end_name, attr.u.str); + } + if (!route_leaves_road && item_attr_get(item, attr_street_name_systematic, &attr)) { + // TODO crude comparison in need of refinement + if (start_ref) + route_leaves_road |= !strcmp(start_ref, attr.u.str); + if (end_ref) + route_leaves_road |= !strcmp(end_ref, attr.u.str); } } map_rect_destroy(mr); } - for (s = p->end; s && !has_offroute_match; s = s->end_next) { + for (s = p->end; s && !(has_offroute_match && route_leaves_road); s = s->end_next) { if ((p->seg == s) || (p_prev && (p_prev->seg == s))) /* segments is on the route, skip */ continue; @@ -1454,17 +1500,38 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, // TODO crude comparison in need of refinement if (!strcmp(this_->junction_name, attr.u.str)) has_offroute_match = 1; + if (start_name) + route_leaves_road |= !strcmp(start_name, attr.u.str); + if (end_name) + route_leaves_road |= !strcmp(end_name, attr.u.str); + } + if (!route_leaves_road && item_attr_get(item, attr_street_name_systematic, &attr)) { + // TODO crude comparison in need of refinement + if (start_ref) + route_leaves_road |= !strcmp(start_ref, attr.u.str); + if (end_ref) + route_leaves_road |= !strcmp(end_ref, attr.u.str); } } map_rect_destroy(mr); } - dbg(lvl_debug, "p=%p: has_offroute_match=%d, has_start_match=%d, has_end_match=%d", - p, has_offroute_match, has_start_match, has_end_match); + dbg(lvl_debug, "p=%p: has_offroute_match=%d, has_start_match=%d, has_end_match=%d, route_follows_road=%d, route_leaves_road=%d", + p, has_offroute_match, has_start_match, has_end_match, route_follows_road, route_leaves_road); + + g_free(start_name); + g_free(start_ref); + g_free(end_name); + g_free(end_ref); + + if (route_leaves_road && !route_follows_road) + want_start_match = !match_start; + /* TODO decide how to handle ambiguous situations (both true or both false), currently we include the segment */ if (has_offroute_match) { if (has_start_match || has_end_match) { /* we cannot have multiple matches in different categories */ + /* TODO maybe we can: e.g. one segment of the crossing road got added to the route, the other did not */ dbg(lvl_debug, "p=%p: both off-route and start/end match, score 0", p); return 0; } -- cgit v1.2.1 From e8fc06aaac552f57c2be9888d632ef7219d471bb Mon Sep 17 00:00:00 2001 From: mvglasow Date: Mon, 7 Jan 2019 21:55:59 +0100 Subject: Refactor:traffic:Include names in debug output for end point matching Signed-off-by: mvglasow --- navit/traffic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/navit/traffic.c b/navit/traffic.c index 77417e4a7..ac44e6828 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -1516,8 +1516,9 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, map_rect_destroy(mr); } - dbg(lvl_debug, "p=%p: has_offroute_match=%d, has_start_match=%d, has_end_match=%d, route_follows_road=%d, route_leaves_road=%d", - p, has_offroute_match, has_start_match, has_end_match, route_follows_road, route_leaves_road); + dbg(lvl_debug, "p=%p: %s %s → %s %s\nhas_offroute_match=%d, has_start_match=%d, has_end_match=%d, route_follows_road=%d, route_leaves_road=%d", + p, end_ref, end_name, start_ref, start_name, + has_offroute_match, has_start_match, has_end_match, route_follows_road, route_leaves_road); g_free(start_name); g_free(start_ref); -- cgit v1.2.1 From 35e1d874036787cf8809cfe6372ffb5be1dd5d23 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Mon, 7 Jan 2019 21:56:33 +0100 Subject: Fix:traffic:Increase penalty for poorly matched end points Signed-off-by: mvglasow --- navit/traffic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/navit/traffic.c b/navit/traffic.c index ac44e6828..20566e59c 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -68,7 +68,7 @@ #define PENALTY_SEGMENT_MATCH 4 /** The maximum penalty applied to points with non-matching attributes */ -#define PENALTY_POINT_MATCH 16 +#define PENALTY_POINT_MATCH 24 /** Flag to indicate expired messages should be purged */ #define PROCESS_MESSAGES_PURGE_EXPIRED 1 << 0 -- cgit v1.2.1 From db03eb60cc5e89ca13ef6ae50ebbb7e41e28db81 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Mon, 7 Jan 2019 23:24:01 +0100 Subject: Refactor:traffic:Fix code style Signed-off-by: mvglasow --- navit/traffic.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/navit/traffic.c b/navit/traffic.c index 20566e59c..a5862a625 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -1516,9 +1516,10 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, map_rect_destroy(mr); } - dbg(lvl_debug, "p=%p: %s %s → %s %s\nhas_offroute_match=%d, has_start_match=%d, has_end_match=%d, route_follows_road=%d, route_leaves_road=%d", - p, end_ref, end_name, start_ref, start_name, - has_offroute_match, has_start_match, has_end_match, route_follows_road, route_leaves_road); + dbg(lvl_debug, + "p=%p: %s %s → %s %s\nhas_offroute_match=%d, has_start_match=%d, has_end_match=%d, route_follows_road=%d, route_leaves_road=%d", + p, end_ref, end_name, start_ref, start_name, + has_offroute_match, has_start_match, has_end_match, route_follows_road, route_leaves_road); g_free(start_name); g_free(start_ref); -- cgit v1.2.1