Skip to content

Commit

Permalink
Optionally add admin crossings to route response (valhalla#4941)
Browse files Browse the repository at this point in the history
Co-authored-by: Kevin Kreiser <[email protected]>
  • Loading branch information
chrstnbwnkl and kevinkreiser authored Oct 31, 2024
1 parent a9071e3 commit 18984b4
Show file tree
Hide file tree
Showing 6 changed files with 440 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* FIXED: Fix ability to use Valhalla via cmake `add_subdirectory` [#4930](https://github.com/valhalla/valhalla/pull/4930)
* **Enhancement**
* ADDED: Consider smoothness in all profiles that use surface [#4949](https://github.com/valhalla/valhalla/pull/4949)
* ADDED: `admin_crossings` request parameter for `/route` [#4941](https://github.com/valhalla/valhalla/pull/4941)

## Release Date: 2024-10-10 Valhalla 3.5.1
* **Removed**
Expand Down
1 change: 1 addition & 0 deletions docs/docs/api/turn-by-turn/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ For example a bus request with the result in Spanish using the OSRM (Open Source
| `linear_references` | When present and `true`, the successful `route` response will include a key `linear_references`. Its value is an array of base64-encoded [OpenLR location references][openlr], one for each graph edge of the road network matched by the input trace. |
| `prioritize_bidirectional` | Prioritize `bidirectional a*` when `date_time.type = depart_at/current`. By default `time_dependent_forward a*` is used in these cases, but `bidirectional a*` is much faster. Currently it does not update the time (and speeds) when searching for the route path, but the ETA on that route is recalculated based on the time-dependent speeds |
| `roundabout_exits` | A boolean indicating whether exit instructions at roundabouts should be added to the output or not. Default is true. |
| `admin_crossings` | When present and `true`, the successful route summary will include the two keys `admins` and `admin_crossings`. `admins` is an array of administrative regions the route lies within. `admin_crossings` is an array of objects that contain `from_admin_index` and `to_admin_index`, which are indices into the `admins` array. They also contain `from_shape_index` and `to_shape_index`, which are start and end indices of the edge along which an administrative boundary is crossed. |

[openlr]: https://www.openlr-association.com/fileadmin/user_upload/openlr-whitepaper_v1.5.pdf

Expand Down
1 change: 1 addition & 0 deletions proto/options.proto
Original file line number Diff line number Diff line change
Expand Up @@ -503,4 +503,5 @@ message Options {
bool voice_instructions = 57; // Whether to return voiceInstructions in the OSRM serializer response
bool dedupe = 58; // Keep track of edges and override their properties during expansion,
// ensuring that each edge appears in the output only once. [default = false]
bool admin_crossings = 59; // Include administrative boundary crossings
}
38 changes: 38 additions & 0 deletions src/tyr/route_serializer_valhalla.cc
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,44 @@ void legs(const valhalla::Api& api, int route_index, rapidjson::writer_wrapper_t
}

writer.start_object("summary");

// Does the user want admin info?
if (api.options().admin_crossings()) {
// write the admin array
writer.start_array("admins");
for (const auto& admin : trip_leg_itr->admin()) {
writer.start_object();
writer("country_code", admin.country_code());
writer("country_text", admin.country_text());
writer("state_code", admin.state_code());
writer("state_text", admin.state_text());
writer.end_object();
}
writer.end_array();

if (trip_leg_itr->admin_size() > 1) {
// write the admin crossings
auto node_itr = trip_leg_itr->node().begin();
auto next_node_itr = trip_leg_itr->node().begin();
next_node_itr++;
writer.start_array("admin_crossings");

while (next_node_itr != trip_leg_itr->node().end()) {
if (next_node_itr->admin_index() != node_itr->admin_index()) {
writer.start_object();
writer("from_admin_index", static_cast<uint64_t>(node_itr->admin_index()));
writer("to_admin_index", static_cast<uint64_t>(next_node_itr->admin_index()));
writer("begin_shape_index", static_cast<uint64_t>(node_itr->edge().begin_shape_index()));
writer("end_shape_index", static_cast<uint64_t>(node_itr->edge().end_shape_index()));
writer.end_object();
}
++node_itr;
++next_node_itr;
}
writer.end_array();
}
}

writer("has_time_restrictions", has_time_restrictions);
writer("has_toll", has_toll);
writer("has_highway", has_highway);
Expand Down
5 changes: 5 additions & 0 deletions src/worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,11 @@ void from_json(rapidjson::Document& doc, Options::Action action, Api& api) {
options.set_linear_references(*linear_references);
}

auto admin_crossings = rapidjson::get_optional<bool>(doc, "/admin_crossings");
if (admin_crossings) {
options.set_admin_crossings(*admin_crossings);
}

// whatever our costing is, check to see if we are going to ignore_closures
std::stringstream ss;
ss << "/costing_options/" << costing_str << "/ignore_closures";
Expand Down
Loading

0 comments on commit 18984b4

Please sign in to comment.