diff options
author | mvglasow <michael@vonglasow.com> | 2019-01-11 20:04:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-11 20:04:39 +0100 |
commit | fabeea80a7f137ddb6e96e48bc543717aa7d5aec (patch) | |
tree | 08543e5adf9361d250857261697501d4d386ec9e | |
parent | 09345bbf2f236aeb33a1a9406b81ec035a01cd8b (diff) | |
parent | 5cf646c8f521db88bb68f5f7ca20c35c3474606b (diff) | |
download | navit-fabeea80a7f137ddb6e96e48bc543717aa7d5aec.tar.gz |
Merge branch 'trunk' into coverity_bypass
-rw-r--r-- | .circleci/config.yml | 42 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | navit/graphics.c | 58 | ||||
-rw-r--r-- | navit/maptool/boundaries.c | 3 | ||||
-rw-r--r-- | navit/maptool/osm.c | 3 | ||||
-rw-r--r-- | navit/traffic.c | 211 | ||||
-rw-r--r-- | navit/transform.c | 9 | ||||
-rwxr-xr-x | scripts/build_android_arm.sh | 61 | ||||
-rw-r--r-- | scripts/build_linux.sh | 7 |
9 files changed, 289 insertions, 109 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index 1cbfd6809..c9b2bd214 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -82,46 +82,12 @@ jobs: command: | sudo apt-get update sudo apt-get install -y cmake gettext libsaxonb-java librsvg2-bin pkg-config libprotobuf-c-dev protobuf-c-compiler - cmake ./ -Dsvg2png_scaling:STRING=-1,24,32,48,64,96,128,192,256 -Dsvg2png_scaling_nav:STRING=-1,24,32,48,64,96,128,192,256 -Dsvg2png_scaling_flag:STRING=-1,24,32,64,96 -DUSE_PLUGINS=n -DBUILD_MAPTOOL=n -DXSL_PROCESSING=y -DXSLTS=android -DANDROID=y -DSAMPLE_MAP=n - run: - name: Process icons - command: | - cd navit/icons - make - mkdir ../android/res/drawable-nodpi - rename 'y/A-Z/a-z/' *.png - cp *.png ../android/res/drawable-nodpi - cd ../../ - - run: - name: Process translations - command: | - cd po - make - mkdir ../navit/android/res/raw - rename 'y/A-Z/a-z/' *.mo - cp *.mo ../navit/android/res/raw - cd ../ - - run: - name: Process xml's - command: | - make navit_config_xml - cd navit - mkdir -p ./android/assets - cp -R config ./android/assets/ - cd ../ - - run: - name: Chmod permissions - command: chmod +x ./gradlew - - run: - name: Download Dependencies - command: ./gradlew -v -# command: ./gradlew androidDependencies - - run: - name: Install ndk - command: sdkmanager ndk-bundle + name: Install Android SDK components + command: sdkmanager ndk-bundle "cmake;3.6.4111459" - run: - name: Build - command: ./gradlew assembleDebug + name: Build for Android (ARM) + command: bash scripts/build_android_arm.sh - run: name: Run Lint Test command: | @@ -77,7 +77,7 @@ Navit reads the current vehicle position: Routing algorithm ================= -Navit uses LPA* (see https://en.wikipedia.org/wiki/Lifelong_Planning_A*), a derivative of the Dijkstra algorithm, for +Navit uses LPA* (see [Lifelong_Planning_A*](https://en.wikipedia.org/wiki/Lifelong_Planning_A*)), a derivative of the Dijkstra algorithm, for routing. Routing starts at the destination by assigning a value to each point directly connected to the destination point. The value represents the estimated time needed to reach the destination from that point. @@ -91,4 +91,4 @@ destination. LPA* is slightly more complex, as it allows partial re-evaluation of the route graph as segment costs change. This is used by the (still experimental) traffic module, which can process traffic reports and tries to find a way around -traffic problems. Refer to the Wikipedia page for a full description.
\ No newline at end of file +traffic problems. Refer to the Wikipedia page for a full description. diff --git a/navit/graphics.c b/navit/graphics.c index 50913eeea..1bb7dbd3c 100644 --- a/navit/graphics.c +++ b/navit/graphics.c @@ -135,7 +135,8 @@ struct displaylist_icon_cache { }; -static void circle_to_points(const struct point *center, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir); +static void circle_to_points(const struct point *center, int diameter, int scale, int start, int len, struct point *res, + int *pos, int dir); static void graphics_process_selection(struct graphics *gra, struct displaylist *dl); static void graphics_gc_init(struct graphics *this_); @@ -251,7 +252,8 @@ void graphics_set_rect(struct graphics *gra, struct point_rect *pr) { struct graphics * graphics_new(struct attr *parent, struct attr **attrs) { struct graphics *this_; struct attr *type_attr, cbl_attr; - struct graphics_priv * (*graphicstype_new)(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl); + struct graphics_priv * (*graphicstype_new)(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, + struct callback_list *cbl); if (! (type_attr=attr_search(attrs, NULL, attr_type))) { dbg(lvl_error,"Graphics plugin type is not set."); @@ -629,7 +631,8 @@ struct graphics_image * graphics_image_new_scaled(struct graphics *gra, char *pa return graphics_image_new_scaled_rotated(gra, path, w, h, 0); } -static void image_new_helper(struct graphics *gra, struct graphics_image *this_, char *path, char *name, int width, int height, int rotate, int zip) { +static void image_new_helper(struct graphics *gra, struct graphics_image *this_, char *path, char *name, int width, + int height, int rotate, int zip) { int i=0; int stdsizes[]= {8,12,16,22,24,32,36,48,64,72,96,128,192,256}; const int numstdsizes=sizeof(stdsizes)/sizeof(int); @@ -725,7 +728,8 @@ static void image_new_helper(struct graphics *gra, struct graphics_image *this_, struct graphics_image_buffer buffer= {"buffer:",graphics_image_type_unknown}; buffer.start=start; buffer.len=len; - this_->priv=gra->meth.image_new(gra->priv, &this_->meth, (char *)&buffer, &this_->width, &this_->height, &this_->hot, rotate); + this_->priv=gra->meth.image_new(gra->priv, &this_->meth, (char *)&buffer, &this_->width, &this_->height, &this_->hot, + rotate); g_free(start); } } else { @@ -929,7 +933,8 @@ void graphics_draw_rectangle(struct graphics *this_, struct graphics_gc *gc, str this_->meth.draw_rectangle(this_->priv, gc->priv, p, w, h); } -void graphics_draw_rectangle_rounded(struct graphics *this_, struct graphics_gc *gc, struct point *plu, int w, int h, int r, int fill) { +void graphics_draw_rectangle_rounded(struct graphics *this_, struct graphics_gc *gc, struct point *plu, int w, int h, + int r, int fill) { struct point *p=g_alloca(sizeof(struct point)*(r*4+32)); struct point pi0= {plu->x+r,plu->y+r}; struct point pi1= {plu->x+w-r,plu->y+r}; @@ -956,7 +961,8 @@ void graphics_draw_rectangle_rounded(struct graphics *this_, struct graphics_gc * @returns <> * @author Martin Schaller (04/2008) */ -void graphics_draw_text(struct graphics *this_, struct graphics_gc *gc1, struct graphics_gc *gc2, struct graphics_font *font, char *text, struct point *p, int dx, int dy) { +void graphics_draw_text(struct graphics *this_, struct graphics_gc *gc1, struct graphics_gc *gc2, + struct graphics_font *font, char *text, struct point *p, int dx, int dy) { this_->meth.draw_text(this_->priv, gc1->priv, gc2 ? gc2->priv : NULL, font->priv, text, p, dx, dy); } @@ -967,7 +973,8 @@ void graphics_draw_text(struct graphics *this_, struct graphics_gc *gc1, struct * @returns <> * @author Martin Schaller (04/2008) */ -void graphics_get_text_bbox(struct graphics *this_, struct graphics_font *font, char *text, int dx, int dy, struct point *ret, int estimate) { +void graphics_get_text_bbox(struct graphics *this_, struct graphics_font *font, char *text, int dx, int dy, + struct point *ret, int estimate) { this_->meth.get_text_bbox(this_->priv, font->priv, text, dx, dy, ret, estimate); } @@ -1143,7 +1150,8 @@ static void xdisplay_free(struct displaylist *dl) { * @returns <> * @author Martin Schaller (04/2008) */ -static void display_add(struct hash_entry *entry, struct item *item, int count, struct coord *c, char **label, int label_count) { +static void display_add(struct hash_entry *entry, struct item *item, int count, struct coord *c, char **label, + int label_count) { struct displayitem *di; int len,i; char *p; @@ -1187,7 +1195,8 @@ static void display_add(struct hash_entry *entry, struct item *item, int count, * @returns <> * @author Martin Schaller (04/2008) */ -static void label_line(struct graphics *gra, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, struct point *p, int count, char *label) { +static void label_line(struct graphics *gra, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, + struct point *p, int count, char *label) { int i,x,y,tl,tlm,th,thm,tlsq,l; float lsq; double dx,dy; @@ -1366,7 +1375,8 @@ struct circle { * @param[out] pos Index of the last point filled inside array @p res * @param dir Direction of the circle (valid values are 1 (counter-clockwise) or -1 (clockwise), other values may lead to unknown result) */ -static void circle_to_points(const struct point *center, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir) { +static void circle_to_points(const struct point *center, int diameter, int scale, int start, int len, struct point *res, + int *pos, int dir) { struct circle *c; int count=64; int end=start+len; @@ -1561,7 +1571,8 @@ static int draw_middle(struct draw_polyline_context *ctx, struct point *p) { draw_point(&ctx->prev_shape, p, &poso, 1); if (delta >= 256) return 0; - if (intersection(&pos, ctx->shape.dx, ctx->shape.dy, &poso, ctx->prev_shape.dx, ctx->prev_shape.dy, &ctx->res[ctx->ppos])) { + if (intersection(&pos, ctx->shape.dx, ctx->shape.dy, &poso, ctx->prev_shape.dx, ctx->prev_shape.dy, + &ctx->res[ctx->ppos])) { ctx->ppos++; draw_point(&ctx->prev_shape, p, &ctx->res[ctx->npos--], 0); draw_point(&ctx->shape, p, &ctx->res[ctx->npos--], 0); @@ -1573,7 +1584,8 @@ static int draw_middle(struct draw_polyline_context *ctx, struct point *p) { draw_point(&ctx->prev_shape, p, &nego, 0); if (delta <= -256) return 0; - if (intersection(&neg, ctx->shape.dx, ctx->shape.dy, &nego, ctx->prev_shape.dx, ctx->prev_shape.dy, &ctx->res[ctx->npos])) { + if (intersection(&neg, ctx->shape.dx, ctx->shape.dy, &nego, ctx->prev_shape.dx, ctx->prev_shape.dy, + &ctx->res[ctx->npos])) { ctx->npos--; draw_point(&ctx->prev_shape, p, &ctx->res[ctx->ppos++], 1); draw_point(&ctx->shape, p, &ctx->res[ctx->ppos++], 1); @@ -1600,7 +1612,9 @@ static void draw_init_ctx(struct draw_polyline_context *ctx, int maxpoints) { } -static void graphics_draw_polyline_as_polygon(struct graphics_priv *gra_priv, struct graphics_gc_priv *gc_priv, struct point *pnt, int count, int *width, void (*draw)(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)) { +static void graphics_draw_polyline_as_polygon(struct graphics_priv *gra_priv, struct graphics_gc_priv *gc_priv, + struct point *pnt, int count, int *width, void (*draw)(struct graphics_priv *gr, struct graphics_gc_priv *gc, + struct point *p, int count)) { int maxpoints=200; struct draw_polyline_context ctx; int i=0; @@ -1657,7 +1671,8 @@ static int relative_pos(struct wpoint *p, struct point_rect *r) { return relative_pos; } -static void clip_line_endoint_to_rect_edge(struct wpoint *p, int rel_pos, int dx, int dy, int dw, struct point_rect *clip_rect) { +static void clip_line_endoint_to_rect_edge(struct wpoint *p, int rel_pos, int dx, int dy, int dw, + struct point_rect *clip_rect) { // We must cast to float to avoid integer // overflow (i.e. undefined behaviour) at high // zoom levels. @@ -1725,7 +1740,8 @@ static int clip_line(struct wpoint *p1, struct wpoint *p2, struct point_rect *cl * @param[in] width An array of width matching the line starting from the corresponding @p pa (if all equal, all lines will have the same width) * @param poly A boolean indicating whether the polyline should be closed to form a polygon (only the contour of this polygon will be drawn) */ -void graphics_draw_polyline_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pa, int count, int *width, int poly) { +void graphics_draw_polyline_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pa, int count, + int *width, int poly) { struct point *points_to_draw=g_alloca(sizeof(struct point)*(count+1)); int *w=g_alloca(sizeof(int)*(count+1)); struct wpoint segment_start,segment_end; @@ -2489,7 +2505,8 @@ static void do_draw(struct displaylist *displaylist, int cancel, int flags) { * @returns <> * @author Martin Schaller (04/2008) */ -void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, struct layout *l, int flags) { +void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, + struct layout *l, int flags) { int order=transform_get_order(trans); if(displaylist->dc.trans && displaylist->dc.trans!=trans) transform_destroy(displaylist->dc.trans); @@ -2520,7 +2537,8 @@ void graphics_displaylist_draw(struct graphics *gra, struct displaylist *display gra->meth.draw_mode(gra->priv, draw_mode_end); } -static void graphics_load_mapset(struct graphics *gra, struct displaylist *displaylist, struct mapset *mapset, struct transformation *trans, struct layout *l, int async, struct callback *cb, int flags) { +static void graphics_load_mapset(struct graphics *gra, struct displaylist *displaylist, struct mapset *mapset, + struct transformation *trans, struct layout *l, int async, struct callback *cb, int flags) { int order=transform_get_order(trans); dbg(lvl_debug,"enter"); @@ -2559,7 +2577,8 @@ static void graphics_load_mapset(struct graphics *gra, struct displaylist *displ * @returns <> * @author Martin Schaller (04/2008) */ -void graphics_draw(struct graphics *gra, struct displaylist *displaylist, struct mapset *mapset, struct transformation *trans, struct layout *l, int async, struct callback *cb, int flags) { +void graphics_draw(struct graphics *gra, struct displaylist *displaylist, struct mapset *mapset, + struct transformation *trans, struct layout *l, int async, struct callback *cb, int flags) { graphics_load_mapset(gra, displaylist, mapset, trans, l, async, cb, flags); } @@ -2808,7 +2827,8 @@ static int within_dist_polygon(struct point *p, struct point *poly_pnt, int coun * @returns <> * @author Martin Schaller (04/2008) */ -int graphics_displayitem_within_dist(struct displaylist *displaylist, struct displayitem *di, struct point *p, int dist) { +int graphics_displayitem_within_dist(struct displaylist *displaylist, struct displayitem *di, struct point *p, + int dist) { struct point *pa=g_alloca(sizeof(struct point)*displaylist->dc.maxlen); int count; diff --git a/navit/maptool/boundaries.c b/navit/maptool/boundaries.c index e7dc90123..2f64d092c 100644 --- a/navit/maptool/boundaries.c +++ b/navit/maptool/boundaries.c @@ -131,7 +131,8 @@ static GList *process_boundaries_setup(FILE *boundaries, struct relations *relat relations_add_relation_member_entry(relations, relations_func, boundary, (gpointer)role, rel_member_way, osm_id); } if(member_type==rel_member_relation) { - if (!g_strcmp0(rolestr,"outer") || !g_strcmp0(rolestr,"exclave") || !g_strcmp0(rolestr,"inner") || !g_strcmp0(rolestr,"enclave")) + if (!g_strcmp0(rolestr,"outer") || !g_strcmp0(rolestr,"exclave") || !g_strcmp0(rolestr,"inner") + || !g_strcmp0(rolestr,"enclave")) has_subrelations++; } } diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index e36234775..f640c8674 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -1619,7 +1619,8 @@ void osm_end_relation(struct maptool_osm *osm) { } else type=type_none; - if ((!g_strcmp0(relation_type, "multipolygon") || !g_strcmp0(relation_type, "boundary")) && (boundary || type!=type_none)) { + if ((!g_strcmp0(relation_type, "multipolygon") || !g_strcmp0(relation_type, "boundary")) + && (boundary || type!=type_none)) { item_bin_write(tmp_item_bin, osm->boundaries); } diff --git a/navit/traffic.c b/navit/traffic.c index 4fafa104d..a5862a625 100644 --- a/navit/traffic.c +++ b/navit/traffic.c @@ -62,10 +62,13 @@ #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 /** 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 @@ -275,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 = { @@ -1319,9 +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. + * + * 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. * @@ -1335,13 +1348,22 @@ 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; /* 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 */ @@ -1356,9 +1378,17 @@ static int traffic_point_match_segment_attributes(struct traffic_point * this_, /* The attribute being examined */ struct attr attr; - if (!this_->junction_name) + /* 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); return 0; + } /* find predecessor of p, if any */ while (p_iter && (p_iter != p)) { @@ -1375,74 +1405,147 @@ 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 */ 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)) { + start_name = g_strdup(attr.u.str); // 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; + } + if (item_attr_get(item, attr_street_name_systematic, &attr)) + start_ref = g_strdup(attr.u.str); + } 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)) { + end_name = g_strdup(attr.u.str); // 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; + } + 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; 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; + 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; 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 + 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 - && !strcmp(this_->junction_name, attr.u.str)) - has_offroute_match = 1; + 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: %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); + 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; } } 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; } } + dbg(lvl_debug, "p=%p: score 100 (full score)", p); return 100; } @@ -1451,17 +1554,18 @@ 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`. * * @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)) @@ -1470,8 +1574,11 @@ 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_OFFROAD - 1) / 100 + over->data.len; + return over->data.len * (100 - over->data.score) * (PENALTY_SEGMENT_MATCH - 1) / 100 + over->data.len; } /** @@ -1886,13 +1993,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; @@ -1973,7 +2081,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); @@ -1998,7 +2106,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); @@ -2612,11 +2720,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"); @@ -2635,9 +2743,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 */ @@ -2648,17 +2756,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"); } @@ -2710,7 +2818,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, @@ -2756,7 +2868,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); @@ -3382,8 +3493,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(); @@ -3545,7 +3660,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) @@ -4179,7 +4294,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), 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 diff --git a/scripts/build_android_arm.sh b/scripts/build_android_arm.sh new file mode 100755 index 000000000..74cf8e28d --- /dev/null +++ b/scripts/build_android_arm.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# Build Navit for Android on ARM. +# +# This script is to be run from the root of the Navit source tree. It is used by CircleCI as well as for local builds, +# in order to keep build environments as uniform as possible and CI test results meaningful. +# +# When running this script locally, ensure all build dependencies are in place: +# - Packages required: cmake gettext libsaxonb-java librsvg2-bin pkg-config libprotobuf-c-dev protobuf-c-compiler +# - Android SDK installed +# - Environment variable $ANDROID_HOME points to Android SDK install location +# - Android NDK and CMake components installed via +# sdkmanager ndk-bundle "cmake;3.6.4111459" +# (later CMake versions from the SDK repository may also work) +# +# If any of the build steps fails, this script aborts with an error immediately. + +echo Set up environment +set - e +export PATH=$PATH:$ANDROID_HOME/tools +export JVM_OPTS="-Xmx3200m" +export GRADLE_OPTS='-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' + +echo Run CMake +cmake ./ -Dvehicle/gpsd_dbus:BOOL=FALSE -Dsvg2png_scaling:STRING=-1,24,32,48,64,96,128,192,256 -Dsvg2png_scaling_nav:STRING=-1,24,32,48,64,96,128,192,256 -Dsvg2png_scaling_flag:STRING=-1,24,32,64,96 -DUSE_PLUGINS=n -DBUILD_MAPTOOL=n -DXSL_PROCESSING=y -DXSLTS=android -DANDROID=y -DSAMPLE_MAP=n || exit 1 + +echo Process icons +cd navit/icons +make || exit 32 +mkdir ../android/res/drawable-nodpi +rename 'y/A-Z/a-z/' ./*.png +cp ./*.png ../android/res/drawable-nodpi +cd ../../ + +echo Process translations +cd po +make || exit 64 +mkdir ../navit/android/res/raw +rename 'y/A-Z/a-z/' ./*.mo +cp ./*.mo ../navit/android/res/raw +cd ../ + +echo Process xml config files +make navit_config_xml || exit 96 +cd navit +mkdir -p ./android/assets +cp -R config ./android/assets/ +cd ../ + +echo Chmod permissions +chmod a+x ./gradlew + +echo Download dependencies +./gradlew -v + +echo Build +./gradlew assembleDebug || exit 128 + +echo Build finished. +echo APK should be in "navit/android/build/outputs/apk" and can be installed with +echo ./gradlew installDebug + diff --git a/scripts/build_linux.sh b/scripts/build_linux.sh index ba04c1efc..5d807ec45 100644 --- a/scripts/build_linux.sh +++ b/scripts/build_linux.sh @@ -10,6 +10,7 @@ cmake_opts="-Dgraphics/qt_qpainter:BOOL=FALSE -Dgui/qml:BOOL=FALSE -DSVG2PNG:BOO pushd $BUILD_PATH # Build everything + echo "Building..." cmake ${cmake_opts} ../ make -j $(nproc --all) make package @@ -19,14 +20,18 @@ if [[ "${CIRCLE_PROJECT_USERNAME}" == "navit-gps" && "${CIRCLE_BRANCH}" == "trun # Temporarily disabled because Coverity is down. # TODO on the long run, CI should not fail just because the Coverity test did not run, # especially if the test results are not taken into account. + #echo "Pushing an update to coverity as we are building the official trunk code." + #echo "Downloading coverity..." #curl \ # -X POST --data "token=${COVERITY_TOKEN}&project=${CIRCLE_PROJECT_USERNAME}" \ # -o /tmp/cov-analysis-linux64-${COVERITY_VERSION}.tar.gz -s \ # https://scan.coverity.com/download/linux64 + #echo "Unpacking coverity..." #tar xfz /tmp/cov-analysis-linux64-${COVERITY_VERSION}.tar.gz --no-same-owner -C /usr/local/share/ #export PATH=/usr/local/share/cov-analysis-linux64-${COVERITY_VERSION}/bin:$PATH + #echo "Re-running build with coverity..." #cov-build --dir cov-int make -j $(nproc --all) #tar czvf navit.tgz cov-int @@ -38,11 +43,13 @@ if [[ "${CIRCLE_PROJECT_USERNAME}" == "navit-gps" && "${CIRCLE_BRANCH}" == "trun # https://scan.coverity.com/builds?project=$CIRCLE_PROJECT_USERNAME # Then update the translation template on launchpad + echo "Updating the translation template on launchpad..." sed -i '/INTEGER/d' po/navit.pot cp po/navit.pot $CIRCLE_ARTIFACTS/ curl "https://translations.launchpad.net/navit/${CIRCLE_BRANCH}/+translations-upload" -H "$lp_cookie" -H "Referer: https://translations.launchpad.net/navit/${CIRCLE_BRANCH}/+translations-upload" -F file=@po/navit.pot | grep title fi if [[ "$CIRCLE_ARTIFACTS" != "" ]]; then + echo "Copying icons to artifacts..." cp -r navit/icons $CIRCLE_ARTIFACTS fi |