Skip to content

Commit

Permalink
Merge pull request #1083 from navit-gps/traff_0_8
Browse files Browse the repository at this point in the history
Add TraFF 0.8 support
  • Loading branch information
mvglasow committed Jan 31, 2021
2 parents 91222b8 + 3aaab0a commit 37f22db
Show file tree
Hide file tree
Showing 12 changed files with 672 additions and 42 deletions.
361 changes: 343 additions & 18 deletions navit/android/src/org/navitproject/navit/NavitTraff.java

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions navit/attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,10 @@ attr_generic_prepend_attr(struct attr **attrs, struct attr *attr) {
*
* If `attrs` does not contain `attr`, this function is a no-op.
*
* Attributes are matched based on their `type` and `u.data` members, thus `attr` can be a shallow copy
* of the attribute, and can match multiple attributes in the list. The `attr` argument itself is not
* changed.
*
* @param attrs The attribute list
* @param attr The attribute to remove from the list
*
Expand Down
70 changes: 60 additions & 10 deletions navit/navit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1613,8 +1613,6 @@ void navit_set_destination(struct navit *this_, struct pcoord *c, const char *de
}
g_free(destination_file);

callback_list_call_attr_0(this_->attr_cbl, attr_destination);

if (this_->route) {
struct attr attr;
int dstcount;
Expand All @@ -1637,10 +1635,12 @@ void navit_set_destination(struct navit *this_, struct pcoord *c, const char *de
g_free(pc);
g_free(destination_file);
}

if (this_->ready == 3 && !(this_->flags & 4))
navit_draw(this_);
}

callback_list_call_attr_0(this_->attr_cbl, attr_destination);

if (this_->route && this_->ready == 3 && !(this_->flags & 4))
navit_draw(this_);
}

/**
Expand Down Expand Up @@ -1683,22 +1683,43 @@ void navit_set_destinations(struct navit *this_, struct pcoord *c, int count, co
g_free(destination_file);
} else
this_->destination_valid=0;
callback_list_call_attr_0(this_->attr_cbl, attr_destination);
if (this_->route) {
if (this_->route)
route_set_destinations(this_->route, c, count, async);

if (this_->ready == 3)
navit_draw(this_);
}
callback_list_call_attr_0(this_->attr_cbl, attr_destination);
if (this_->route && this_->ready == 3)
navit_draw(this_);
}

/**
* @brief Retrieves destinations from the route
*
* Prior to calling this method, you may want to retrieve the number of destinations by calling
* {@link navit_get_destination_count(struct navit *)} and assigning a buffer of sufficient capacity.
*
* If the return value equals `count`, the buffer was either just large enough or too small to hold the
* entire list of destinations; there is no way to tell from the result which is the case.
*
* If the Navit instance does not have a route, the result is 0.
*
* @param this_ The Navit instance
* @param pc Pointer to an array of projected coordinates which will receive the destination coordinates
* @param count Capacity of `pc`
* @return The number of destinations stored in `pc`, never greater than `count`
*/
int navit_get_destinations(struct navit *this_, struct pcoord *pc, int count) {
if(!this_->route)
return 0;
return route_get_destinations(this_->route, pc, count);

}

/**
* @brief Get the destinations count for the route
*
* @param this The Navit instance
* @return destination count for the route, or 0 if the Navit instance has no route
*/
int navit_get_destination_count(struct navit *this_) {
if(!this_->route)
return 0;
Expand Down Expand Up @@ -3685,7 +3706,36 @@ int navit_get_blocked(struct navit *this_) {

void navit_destroy(struct navit *this_) {
dbg(lvl_debug,"enter %p",this_);
GList *mapsets;
struct map * map;
struct attr attr;
graphics_draw_cancel(this_->gra, this_->displaylist);

mapsets = this_->mapsets;
while (mapsets) {
GList *maps = NULL;
struct mapset_handle *msh;
msh = mapset_open(mapsets->data);
while (msh && (map = mapset_next(msh, 0))) {
/* Add traffic map (identified by the `attr_traffic` attribute) to list of maps to remove */
if (map_get_attr(map, attr_traffic, &attr, NULL))
maps = g_list_append(maps, map);
}
mapset_close(msh);

/* Remove traffic maps, if any */
while (maps) {
attr.type = attr_map;
attr.u.map = maps->data;
mapset_remove_attr(mapsets->data, &attr);
attr_free_content(&attr);
maps = g_list_next(maps);
}
if (maps)
g_list_free(maps);
mapsets = g_list_next(mapsets);
}

callback_list_call_attr_1(this_->attr_cbl, attr_destroy, this_);
attr_list_free(this_->attrs);

Expand Down
27 changes: 26 additions & 1 deletion navit/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,17 @@ struct map_selection *route_selection;

/**
* @brief Returns a single map selection
*
* The boundaries of the selection are determined as follows: First a rectangle spanning `c1` and `c2` is
* built (the two coordinates can be any two opposite corners of the rectangle). Then its maximum extension
* (height or width) is determined and multiplied with the percentage specified by `rel`. The resulting
* amount of padding is added to each edge. After that, the amount specified by `abs` is added to each edge.
*
* @param order Map order (deepest tile level) to select
* @param c1 First coordinate
* @param c2 Second coordinate
* @param rel Relative padding to add to the selection rectangle, in percent
* @param abs Absolute padding to add to the selection rectangle
*/
struct map_selection *
route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs) {
Expand Down Expand Up @@ -1063,7 +1074,7 @@ struct map_selection * route_get_selection(struct route * this_) {
*
* @param sel Start of the list to be destroyed
*/
static void route_free_selection(struct map_selection *sel) {
void route_free_selection(struct map_selection *sel) {
struct map_selection *next;
while (sel) {
next=sel->next;
Expand Down Expand Up @@ -1130,6 +1141,20 @@ void route_set_destinations(struct route *this, struct pcoord *dst, int count, i
profile(0,"end");
}

/**
* @brief Retrieves destinations from the route
*
* Prior to calling this method, you may want to retrieve the number of destinations by calling
* {@link route_get_destination_count(struct route *)} and assigning a buffer of sufficient capacity.
*
* If the return value equals `count`, the buffer was either just large enough or too small to hold the
* entire list of destinations; there is no way to tell from the result which is the case.
*
* @param this The route instance
* @param pc Pointer to an array of projected coordinates which will receive the destination coordinates
* @param count Capacity of `pc`
* @return The number of destinations stored in `pc`, never greater than `count`
*/
int route_get_destinations(struct route *this, struct pcoord *pc, int count) {
int ret=0;
GList *l=this->destinations;
Expand Down
1 change: 1 addition & 0 deletions navit/route_protected.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ struct route_graph {
/* prototypes */
struct route_graph * route_get_graph(struct route *this_);
struct map_selection * route_get_selection(struct route * this_);
void route_free_selection(struct map_selection *sel);
void route_add_traffic_distortion(struct route *this_, struct item *item);
void route_remove_traffic_distortion(struct route *this_, struct item *item);
void route_change_traffic_distortion(struct route *this_, struct item *item);
Expand Down
31 changes: 20 additions & 11 deletions navit/traffic.c
Original file line number Diff line number Diff line change
Expand Up @@ -3842,31 +3842,33 @@ static int traffic_message_is_valid(struct traffic_message * this_) {
return 0;
}
if (!this_->receive_time || !this_->update_time) {
dbg(lvl_debug, "receive_time or update_time not supplied");
dbg(lvl_debug, "%s: receive_time or update_time not supplied", this_->id);
return 0;
}
if (!this_->is_cancellation) {
if (!this_->expiration_time && !this_->end_time) {
dbg(lvl_debug, "not a cancellation, but neither expiration_time nor end_time supplied");
dbg(lvl_debug, "%s: not a cancellation, but neither expiration_time nor end_time supplied",
this_->id);
return 0;
}
if (!this_->location) {
dbg(lvl_debug, "not a cancellation, but no location supplied");
dbg(lvl_debug, "%s: not a cancellation, but no location supplied", this_->id);
return 0;
}
if (!traffic_location_is_valid(this_->location)) {
dbg(lvl_debug, "not a cancellation, but location is invalid");
dbg(lvl_debug, "%s: not a cancellation, but location is invalid", this_->id);
return 0;
}
if (!this_->event_count || !this_->events) {
dbg(lvl_debug, "not a cancellation, but no events supplied");
dbg(lvl_debug, "%s: not a cancellation, but no events supplied", this_->id);
return 0;
}
for (i = 0; i < this_->event_count; i++)
if (this_->events[i])
has_valid_events |= traffic_event_is_valid(this_->events[i]);
if (!has_valid_events) {
dbg(lvl_debug, "not a cancellation, but all events (%d in total) are invalid", this_->event_count);
dbg(lvl_debug, "%s: not a cancellation, but all events (%d in total) are invalid",
this_->id, this_->event_count);
return 0;
}
}
Expand Down Expand Up @@ -4626,7 +4628,6 @@ static struct traffic * traffic_new(struct attr *parent, struct attr **attrs) {
navit_object_destroy((struct navit_object *) this_);
return NULL;
}
navit_object_ref((struct navit_object *) this_);
dbg(lvl_debug,"return %p", this_);

// TODO do this once and cycle through all plugins
Expand Down Expand Up @@ -4888,7 +4889,7 @@ static void traffic_xml_end(xml_context *dummy, const char *tag_name, void *data
count,
(struct traffic_event **) children);
if (!traffic_message_is_valid(message)) {
dbg(lvl_error, "malformed message detected, skipping");
dbg(lvl_error, "%s: malformed message detected, skipping", message->id);
traffic_message_destroy(message);
} else
state->messages = g_list_append(state->messages, message);
Expand Down Expand Up @@ -4945,7 +4946,9 @@ static void traffic_xml_end(xml_context *dummy, const char *tag_name, void *data
state->si = NULL;
/* TODO preserve unknown (and thus invalid) events if they have maxspeed set */
if (!traffic_event_is_valid(event)) {
dbg(lvl_debug, "invalid or unknown event detected, skipping");
dbg(lvl_debug, "invalid or unknown event %s/%s detected, skipping",
traffic_xml_get_attr("class", el->names, el->values),
traffic_xml_get_attr("type", el->names, el->values));
traffic_event_destroy(event);
} else
state->events = g_list_append(state->events, event);
Expand Down Expand Up @@ -5800,7 +5803,6 @@ struct map * traffic_get_map(struct traffic *this_) {
attrs[4] = NULL;

this_->shared->map = map_new(NULL, attrs);
navit_object_ref((struct navit_object *) this_->shared->map);

/* populate map with previously stored messages */
filename = g_strjoin(NULL, navit_get_user_data_directory(TRUE), "/traffic.xml", NULL);
Expand Down Expand Up @@ -5938,6 +5940,13 @@ void traffic_set_route(struct traffic *this_, struct route *rt) {
this_->shared->rt = rt;
}

void traffic_destroy(struct traffic *this_) {
if (this_->meth.destroy)
this_->meth.destroy(this_->priv);
attr_list_free(this_->attrs);
g_free(this_);
}

struct object_func traffic_func = {
attr_traffic,
(object_func_new)traffic_new,
Expand All @@ -5948,7 +5957,7 @@ struct object_func traffic_func = {
(object_func_add_attr)navit_object_add_attr,
(object_func_remove_attr)navit_object_remove_attr,
(object_func_init)NULL,
(object_func_destroy)navit_object_destroy,
(object_func_destroy)traffic_destroy,
(object_func_dup)NULL,
(object_func_ref)navit_object_ref,
(object_func_unref)navit_object_unref,
Expand Down
24 changes: 24 additions & 0 deletions navit/traffic.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,24 @@
extern "C" {
#endif

/**
* @brief Translates a Navit tile order to a minimum road class as used in TraFF.
*
* This can be used to translate a map selection into a TraFF filter.
*
* The tile order is the lowest tile level in which an object of a certain type can be placed (higher numbers
* correspond to lower levels). Currently, 8 is the maximum order for `highway_city`, `highway_land` and
* `street_n_lanes`, equivalent to `MOTORWAY` and `TRUNK`. 10 is the maximum order for `street_4_city` and
* `street_4_land` (`SECONDARY`), 12 for `street_3_city` and `street_3_land` (`TERTIARY`). All others can
* be placed in any tile level.
*
* This macro returns `PRIMARY`, `SECONDARY` and `TERTIARY` for the three bins above these cut-off orders,
* corresponding to one level below the lowest road class we expect to find there. (Not considering that
* low-level roads can be placed into higher-level tiles if they cross a tile boundary of the next lower
* level.) Below the lowest cut-off order, the macro returns NULL.
*/
#define order_to_min_road_class(x) (x <= 8 ? "PRIMARY" : x <= 10 ? "SECONDARY" : x <= 12 ? "TERTIARY" : NULL)

/**
* @brief Classes for events.
*/
Expand Down Expand Up @@ -239,6 +257,7 @@ struct traffic_message_priv;
*/
struct traffic_methods {
struct traffic_message **(* get_messages)(struct traffic_priv * this_); /**< Retrieves new messages from the traffic plugin */
void (*destroy)(struct traffic_priv * this_); /**< Destructor for the traffic plugin */
};

/**
Expand Down Expand Up @@ -989,6 +1008,11 @@ void traffic_set_mapset(struct traffic *this_, struct mapset *ms);
*/
void traffic_set_route(struct traffic *this_, struct route *rt);

/**
* @brief Destructor.
*/
void traffic_destroy(struct traffic *this_);

/* end of prototypes */
#ifdef __cplusplus
}
Expand Down
1 change: 1 addition & 0 deletions navit/traffic/dummy/traffic_dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ struct traffic_message ** traffic_dummy_get_messages(struct traffic_priv * this_
*/
static struct traffic_methods traffic_dummy_meth = {
traffic_dummy_get_messages,
NULL,
};

/**
Expand Down
1 change: 1 addition & 0 deletions navit/traffic/null/traffic_null.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct traffic_message ** traffic_null_get_messages(struct traffic_priv * this_)
*/
static struct traffic_methods traffic_null_meth = {
traffic_null_get_messages,
NULL,
};

/**
Expand Down

0 comments on commit 37f22db

Please sign in to comment.