diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp index ad0134067..7e2117da7 100644 --- a/data_structures/route_parameters.cpp +++ b/data_structures/route_parameters.cpp @@ -118,16 +118,17 @@ void RouteParameters::addTimestamp(const unsigned timestamp) } } -void RouteParameters::addBearing(const int bearing, boost::spirit::qi::unused_type unused, bool& pass) +void RouteParameters::addBearing( + const boost::fusion::vector> &received_bearing, + boost::spirit::qi::unused_type /* unused */, bool& pass) { - bearings.resize(coordinates.size()); pass = false; + const int bearing = boost::fusion::at_c<0>(received_bearing); + const boost::optional range = boost::fusion::at_c<1>(received_bearing); if (bearing < 0 || bearing > 359) return; - if (!bearings.empty()) - { - bearings.back() = bearing; - pass = true; - } + if (range && (*range < 0 || *range > 180)) return; + bearings.emplace_back(std::make_pair(bearing,range)); + pass = true; } void RouteParameters::setLanguage(const std::string &language_string) diff --git a/features/step_definitions/matching.rb b/features/step_definitions/matching.rb index b82051949..06d00da1f 100644 --- a/features/step_definitions/matching.rb +++ b/features/step_definitions/matching.rb @@ -8,6 +8,17 @@ When /^I match I should get$/ do |table| response = request_url row['request'] else params = @query_params + got = {} + row.each_pair do |k,v| + if k =~ /param:(.*)/ + if v=='(nil)' + params[$1]=nil + elsif v!=nil + params[$1]=v + end + got[k]=v + end + end trace = [] timestamps = [] if row['trace'] @@ -19,24 +30,13 @@ When /^I match I should get$/ do |table| if row['timestamps'] timestamps = row['timestamps'].split(" ").compact.map { |t| t.to_i} end - got = {'trace' => row['trace'] } + got = got.merge({'trace' => row['trace'] }) response = request_matching trace, timestamps, params else raise "*** no trace" end end - row.each_pair do |k,v| - if k =~ /param:(.*)/ - if v=='(nil)' - params[$1]=nil - elsif v!=nil - params[$1]=v - end - got[k]=v - end - end - if response.body.empty? == false json = JSON.parse response.body end diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index ee3634ab4..ff6625682 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -8,6 +8,17 @@ When /^I route I should get$/ do |table| response = request_url row['request'] else params = @query_params + got = {} + row.each_pair do |k,v| + if k =~ /param:(.*)/ + if v=='(nil)' + params[$1]=nil + elsif v!=nil + params[$1]=v + end + got[k]=v + end + end waypoints = [] if row['from'] and row['to'] node = find_node_by_name(row['from']) @@ -18,7 +29,7 @@ When /^I route I should get$/ do |table| raise "*** unknown to-node '#{row['to']}" unless node waypoints << node - got = {'from' => row['from'], 'to' => row['to'] } + got = got.merge({'from' => row['from'], 'to' => row['to'] }) response = request_route waypoints, params elsif row['waypoints'] row['waypoints'].split(',').each do |n| @@ -26,24 +37,13 @@ When /^I route I should get$/ do |table| raise "*** unknown waypoint node '#{n.strip}" unless node waypoints << node end - got = {'waypoints' => row['waypoints'] } + got = got.merge({'waypoints' => row['waypoints'] }) response = request_route waypoints, params else raise "*** no waypoints" end end - row.each_pair do |k,v| - if k =~ /param:(.*)/ - if v=='(nil)' - params[$1]=nil - elsif v!=nil - params[$1]=v - end - got[k]=v - end - end - if response.body.empty? == false json = JSON.parse response.body end diff --git a/features/testbot/bearing_param.feature b/features/testbot/bearing_param.feature index 810f69038..b0602d002 100644 --- a/features/testbot/bearing_param.feature +++ b/features/testbot/bearing_param.feature @@ -1,10 +1,26 @@ -@routing @bearing_param @todo @testbot +@routing @bearing_param @testbot Feature: Bearing parameter Background: Given the profile "testbot" And a grid size of 10 meters + Scenario: Testbot - Intial bearing in simple case + Given the node map + | a | b | c | d | + + And the ways + | nodes | + | ad | + + When I route I should get + | from | to | param:b | route | bearing | + | b | c | 90&b=90 | ad | 90 | + | b | c | 180&b=90 | | | + | b | c | 80&b=100 | ad | 90 | + | b | c | 79&b=100 | | | + | b | c | 79,11&b=100 | ad | 90 | + Scenario: Testbot - Intial bearing in simple case Given the node map | a | | @@ -17,13 +33,13 @@ Feature: Bearing parameter | bc | When I route I should get - | from | to | param:bearing | route | bearing | - | 0 | c | 0 | bc | 45 | - | 0 | c | 45 | bc | 45 | - | 0 | c | 85 | bc | 45 | - | 0 | c | 95 | ac | 135 | - | 0 | c | 135 | ac | 135 | - | 0 | c | 180 | ac | 135 | + | from | to | param:b | route | bearing | + | 0 | c | 0&b=0 | | | + | 0 | c | 45&b=45 | bc | 45 ~3% | + | 0 | c | 85&b=85 | | | + | 0 | c | 95&b=95 | | | + | 0 | c | 135&b=135 | ac | 135 ~1% | + | 0 | c | 180&b=180 | | | Scenario: Testbot - Initial bearing on split way Given the node map @@ -38,23 +54,21 @@ Feature: Bearing parameter | da | yes | When I route I should get - | from | to | param:bearing | route | bearing | - | 0 | b | 10 | ab | 90 | - | 0 | b | 90 | ab | 90 | - | 0 | b | 170 | ab | 90 | - | 0 | b | 190 | cd,da,ab | 270 | - | 0 | b | 270 | cd,da,ab | 270 | - | 0 | b | 350 | cd,da,ab | 270 | - | 1 | d | 10 | cd | 90 | - | 1 | d | 90 | cd | 90 | - | 1 | d | 170 | cd | 90 | - | 1 | d | 190 | ab,bc,cd | 270 | - | 1 | d | 270 | ab,bc,cd | 270 | - | 1 | d | 350 | ab,bc,cd | 270 | + | from | to | param:b | route | bearing | + | 0 | b | 10&b=10 | | | + | 0 | b | 90&b=90 | ab | 90 | + | 0 | b | 170&b=170 | | | + | 0 | b | 190&b=190 | | | + | 0 | 1 | 90&b=270 | ab,bc,cd | 90,0,270 | + | 1 | d | 10&b=10 | | | + | 1 | d | 90&b=90 | | | + | 1 | 0 | 190&b=190 | | | + | 1 | d | 270&b=270 | cd | 270 | + | 1 | d | 350&b=350 | | | Scenario: Testbot - Initial bearing in all direction Given the node map - | h | | | a | | | b | + | h | | q | a | | | b | | | | | | | | | | | | p | i | j | | | | g | | o | 0 | k | | c | @@ -82,12 +96,12 @@ Feature: Bearing parameter | ha | yes | When I route I should get - | from | to | param:bearing | route | bearing | - | 0 | a | 0 | ia | 0 | - | 0 | a | 45 | jb,bc,cd,de,ef,fg,gh,ha | 45 | - | 0 | a | 90 | kc,cd,de,ef,fg,gh,ha | 90 | - | 0 | a | 135 | ld,de,ef,fg,gh,ha | 135 | - | 0 | a | 180 | me,de,ef,fg,gh,ha | 180 | - | 0 | a | 225 | nf,ef,fg,gh,ha | 225 | - | 0 | a | 270 | og,gh,ha | 270 | - | 0 | a | 315 | pn,ha | 315 | + | from | to | param:b | route | bearing | + | i | q | 0&b=90 | ia,ab,bc,cd,de,ef,fg,gh,ha | 0,90,180,180,270,270,0,0,90 | + | 0 | a | 45&b=90 | jb,bc,cd,de,ef,fg,gh,ha | 45,180,180,270,270,0,0,90 | + | j | q | 90&b=90 | kc,cd,de,ef,fg,gh,ha | 90,180,270,270,0,0,90 | + | k | a | 135&b=90 | ld,de,ef,fg,gh,ha | 135,270,270,0,0,90 | + | 0 | a | 180&b=90 | me,ef,fg,gh,ha | 180,270,0,0,90 | + | m | a | 225&b=90 | nf,fg,gh,ha | 225,0,0,90 | + | 0 | a | 270&b=90 | og,gh,ha | 270,0,90 | + | 0 | a | 315&b=90 | ph,ha | 315,90 | diff --git a/include/osrm/route_parameters.hpp b/include/osrm/route_parameters.hpp index f49d4408d..1b2a698ea 100644 --- a/include/osrm/route_parameters.hpp +++ b/include/osrm/route_parameters.hpp @@ -72,7 +72,7 @@ struct RouteParameters void addTimestamp(const unsigned timestamp); - void addBearing(const int timestamp, boost::spirit::qi::unused_type unused, bool& pass); + void addBearing(const boost::fusion::vector> &received_bearing, boost::spirit::qi::unused_type unused, bool& pass); void setLanguage(const std::string &language); @@ -102,7 +102,7 @@ struct RouteParameters std::string language; std::vector hints; std::vector timestamps; - std::vector bearings; + std::vector>> bearings; std::vector uturns; std::vector coordinates; }; diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index d7a980419..df4de54c5 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_table.hpp @@ -75,6 +75,13 @@ template class DistanceTablePlugin final : public BasePlugin return 400; } + const auto &input_bearings = route_parameters.bearings; + if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size()) + { + json_result.values["status"] = "Number of bearings does not match number of coordinates ."; + return 400; + } + const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); unsigned max_locations = std::min(static_cast(max_locations_distance_table), @@ -94,8 +101,10 @@ template class DistanceTablePlugin final : public BasePlugin continue; } } + const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0; + const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180; facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], - phantom_node_vector[i], 1); + phantom_node_vector[i], 1, bearing, range); BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes())); } diff --git a/plugins/match.hpp b/plugins/match.hpp index 978c27376..d12ed4666 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -94,7 +94,7 @@ template class MapMatchingPlugin : public BasePlugin } bool getCandidates(const std::vector &input_coords, - const std::vector &input_bearings, + const std::vector>> &input_bearings, const double gps_precision, std::vector &sub_trace_lengths, osrm::matching::CandidateLists &candidates_lists) @@ -130,8 +130,8 @@ template class MapMatchingPlugin : public BasePlugin std::vector> candidates; // Use bearing values if supplied, otherwise fallback to 0,180 defaults - auto bearing = input_bearings.size() > 0 ? input_bearings[current_coordinate] : 0; - auto range = input_bearings.size() > 0 ? 10 : 180; + auto bearing = input_bearings.size() > 0 ? input_bearings[current_coordinate].first : 0; + auto range = input_bearings.size() > 0 ? (input_bearings[current_coordinate].second ? *input_bearings[current_coordinate].second : 10 ) : 180; facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance( input_coords[current_coordinate], candidates, query_radius, bearing, range); diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index bf4cff3a1..e3cf72ed5 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.hpp @@ -58,11 +58,21 @@ template class NearestPlugin final : public BasePlugin { return 400; } + + const auto &input_bearings = route_parameters.bearings; + if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size()) + { + json_result.values["status"] = "Number of bearings does not match number of coordinates ."; + return 400; + } + auto number_of_results = static_cast(route_parameters.num_results); std::vector phantom_node_vector; + const int bearing = input_bearings.size() > 0 ? input_bearings.front().first : 0; + const int range = input_bearings.size() > 0 ? (input_bearings.front().second?*input_bearings.front().second:10) : 180; facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(), phantom_node_vector, - static_cast(number_of_results)); + static_cast(number_of_results), bearing, range); if (phantom_node_vector.empty() || !phantom_node_vector.front().is_valid()) { diff --git a/plugins/trip.hpp b/plugins/trip.hpp index 2567db494..ad5ff99b8 100644 --- a/plugins/trip.hpp +++ b/plugins/trip.hpp @@ -76,6 +76,7 @@ template class RoundTripPlugin final : public BasePlugin PhantomNodeArray &phantom_node_vector) { const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); + const auto &input_bearings = route_parameters.bearings; // find phantom nodes for all input coords for (const auto i : osrm::irange(0, route_parameters.coordinates.size())) @@ -92,8 +93,10 @@ template class RoundTripPlugin final : public BasePlugin continue; } } + const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0; + const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180; facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], - phantom_node_vector[i], 1); + phantom_node_vector[i], 1, bearing, range); if (phantom_node_vector[i].size() > 1) { phantom_node_vector[i].erase(std::begin(phantom_node_vector[i])); @@ -239,6 +242,13 @@ template class RoundTripPlugin final : public BasePlugin return 400; } + const auto &input_bearings = route_parameters.bearings; + if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size()) + { + json_result.values["status"] = "Number of bearings does not match number of coordinates ."; + return 400; + } + // get phantom nodes PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size()); GetPhantomNodes(route_parameters, phantom_node_vector); diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index c054b0dd2..6e898e0a8 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -1,210 +1,210 @@ -/* - -Copyright (c) 2015, Project OSRM contributors -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#ifndef VIA_ROUTE_HPP -#define VIA_ROUTE_HPP - -#include "plugin_base.hpp" - -#include "../algorithms/object_encoder.hpp" -#include "../data_structures/search_engine.hpp" -#include "../descriptors/descriptor_base.hpp" -#include "../descriptors/gpx_descriptor.hpp" -#include "../descriptors/json_descriptor.hpp" -#include "../util/integer_range.hpp" -#include "../util/json_renderer.hpp" -#include "../util/make_unique.hpp" -#include "../util/simple_logger.hpp" -#include "../util/timing_util.hpp" - -#include - -#include - -#include -#include -#include -#include - -template class ViaRoutePlugin final : public BasePlugin -{ - private: - DescriptorTable descriptor_table; - std::string descriptor_string; - std::unique_ptr> search_engine_ptr; - DataFacadeT *facade; - - public: - explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade) - { - search_engine_ptr = osrm::make_unique>(facade); - - descriptor_table.emplace("json", 0); - descriptor_table.emplace("gpx", 1); - // descriptor_table.emplace("geojson", 2); - } - - virtual ~ViaRoutePlugin() {} - - const std::string GetDescriptor() const override final { return descriptor_string; } - - int HandleRequest(const RouteParameters &route_parameters, - osrm::json::Object &json_result) override final - { - if (!check_all_coordinates(route_parameters.coordinates)) - { - return 400; - } - - const auto &input_bearings = route_parameters.bearings; - if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size()) - { - json_result.values["status"] = "Number of bearings does not match number of coordinates ."; - return 400; - } - - std::vector phantom_node_pair_list(route_parameters.coordinates.size()); - const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); - - for (const auto i : osrm::irange(0, route_parameters.coordinates.size())) - { - if (checksum_OK && i < route_parameters.hints.size() && - !route_parameters.hints[i].empty()) - { - ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], - phantom_node_pair_list[i]); - if (phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes())) - { - continue; - } - } - std::vector phantom_node_vector; - int bearing = input_bearings.size() > 0 ? input_bearings[i] : 0; - int range = input_bearings.size() > 0 ? 8 : 180; - if (facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], - phantom_node_vector, 1, bearing, range)) - { - BOOST_ASSERT(!phantom_node_vector.empty()); - phantom_node_pair_list[i].first = phantom_node_vector.front(); - if (phantom_node_vector.size() > 1) - { - phantom_node_pair_list[i].second = phantom_node_vector.back(); - } - } - } - - auto check_component_id_is_tiny = [](const phantom_node_pair &phantom_pair) - { - return phantom_pair.first.is_in_tiny_component(); - }; - - const bool every_phantom_is_in_tiny_cc = - std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), - check_component_id_is_tiny); - - // are all phantoms from a tiny cc? - const auto component_id = phantom_node_pair_list.front().first.component_id; - - auto check_component_id_is_equal = [component_id](const phantom_node_pair &phantom_pair) - { - return component_id == phantom_pair.first.component_id; - }; - - const bool every_phantom_has_equal_id = - std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), - check_component_id_is_equal); - - auto swap_phantom_from_big_cc_into_front = [](phantom_node_pair &phantom_pair) - { - if (0 != phantom_pair.first.component_id && 0 == phantom_pair.second.component_id) - { - using namespace std; - swap(phantom_pair.first, phantom_pair.second); - } - }; - - // this case is true if we take phantoms from the big CC - if (!every_phantom_is_in_tiny_cc || !every_phantom_has_equal_id) - { - std::for_each(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), - swap_phantom_from_big_cc_into_front); - } - - InternalRouteResult raw_route; - auto build_phantom_pairs = - [&raw_route](const phantom_node_pair &first_pair, const phantom_node_pair &second_pair) - { - raw_route.segment_end_coordinates.emplace_back( - PhantomNodes{first_pair.first, second_pair.first}); - }; - osrm::for_each_pair(phantom_node_pair_list, build_phantom_pairs); - - if (1 == raw_route.segment_end_coordinates.size()) - { - if (route_parameters.alternate_route) - { - search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(), - raw_route); - } - else - { - search_engine_ptr->direct_shortest_path(raw_route.segment_end_coordinates, - route_parameters.uturns, raw_route); - } - } - else - { - search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, - route_parameters.uturns, raw_route); - } - - if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) - { - SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found"; - } - - std::unique_ptr> descriptor; - switch (descriptor_table.get_id(route_parameters.output_format)) - { - case 1: - descriptor = osrm::make_unique>(facade); - break; - // case 2: - // descriptor = osrm::make_unique>(); - // break; - default: - descriptor = osrm::make_unique>(facade); - break; - } - - descriptor->SetConfig(route_parameters); - descriptor->Run(raw_route, json_result); - return 200; - } -}; - -#endif // VIA_ROUTE_HPP +/* + +Copyright (c) 2015, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef VIA_ROUTE_HPP +#define VIA_ROUTE_HPP + +#include "plugin_base.hpp" + +#include "../algorithms/object_encoder.hpp" +#include "../data_structures/search_engine.hpp" +#include "../descriptors/descriptor_base.hpp" +#include "../descriptors/gpx_descriptor.hpp" +#include "../descriptors/json_descriptor.hpp" +#include "../util/integer_range.hpp" +#include "../util/json_renderer.hpp" +#include "../util/make_unique.hpp" +#include "../util/simple_logger.hpp" +#include "../util/timing_util.hpp" + +#include + +#include + +#include +#include +#include +#include + +template class ViaRoutePlugin final : public BasePlugin +{ + private: + DescriptorTable descriptor_table; + std::string descriptor_string; + std::unique_ptr> search_engine_ptr; + DataFacadeT *facade; + + public: + explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade) + { + search_engine_ptr = osrm::make_unique>(facade); + + descriptor_table.emplace("json", 0); + descriptor_table.emplace("gpx", 1); + // descriptor_table.emplace("geojson", 2); + } + + virtual ~ViaRoutePlugin() {} + + const std::string GetDescriptor() const override final { return descriptor_string; } + + int HandleRequest(const RouteParameters &route_parameters, + osrm::json::Object &json_result) override final + { + if (!check_all_coordinates(route_parameters.coordinates)) + { + return 400; + } + + const auto &input_bearings = route_parameters.bearings; + if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size()) + { + json_result.values["status"] = "Number of bearings does not match number of coordinates ."; + return 400; + } + + std::vector phantom_node_pair_list(route_parameters.coordinates.size()); + const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); + + for (const auto i : osrm::irange(0, route_parameters.coordinates.size())) + { + if (checksum_OK && i < route_parameters.hints.size() && + !route_parameters.hints[i].empty()) + { + ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], + phantom_node_pair_list[i]); + if (phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes())) + { + continue; + } + } + std::vector phantom_node_vector; + const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0; + const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180; + if (facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], + phantom_node_vector, 1, bearing, range)) + { + BOOST_ASSERT(!phantom_node_vector.empty()); + phantom_node_pair_list[i].first = phantom_node_vector.front(); + if (phantom_node_vector.size() > 1) + { + phantom_node_pair_list[i].second = phantom_node_vector.back(); + } + } + } + + auto check_component_id_is_tiny = [](const phantom_node_pair &phantom_pair) + { + return phantom_pair.first.is_in_tiny_component(); + }; + + const bool every_phantom_is_in_tiny_cc = + std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), + check_component_id_is_tiny); + + // are all phantoms from a tiny cc? + const auto component_id = phantom_node_pair_list.front().first.component_id; + + auto check_component_id_is_equal = [component_id](const phantom_node_pair &phantom_pair) + { + return component_id == phantom_pair.first.component_id; + }; + + const bool every_phantom_has_equal_id = + std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), + check_component_id_is_equal); + + auto swap_phantom_from_big_cc_into_front = [](phantom_node_pair &phantom_pair) + { + if (0 != phantom_pair.first.component_id && 0 == phantom_pair.second.component_id) + { + using namespace std; + swap(phantom_pair.first, phantom_pair.second); + } + }; + + // this case is true if we take phantoms from the big CC + if (!every_phantom_is_in_tiny_cc || !every_phantom_has_equal_id) + { + std::for_each(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list), + swap_phantom_from_big_cc_into_front); + } + + InternalRouteResult raw_route; + auto build_phantom_pairs = + [&raw_route](const phantom_node_pair &first_pair, const phantom_node_pair &second_pair) + { + raw_route.segment_end_coordinates.emplace_back( + PhantomNodes{first_pair.first, second_pair.first}); + }; + osrm::for_each_pair(phantom_node_pair_list, build_phantom_pairs); + + if (1 == raw_route.segment_end_coordinates.size()) + { + if (route_parameters.alternate_route) + { + search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(), + raw_route); + } + else + { + search_engine_ptr->direct_shortest_path(raw_route.segment_end_coordinates, + route_parameters.uturns, raw_route); + } + } + else + { + search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, + route_parameters.uturns, raw_route); + } + + if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length) + { + SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found"; + } + + std::unique_ptr> descriptor; + switch (descriptor_table.get_id(route_parameters.output_format)) + { + case 1: + descriptor = osrm::make_unique>(facade); + break; + // case 2: + // descriptor = osrm::make_unique>(); + // break; + default: + descriptor = osrm::make_unique>(facade); + break; + } + + descriptor->SetConfig(route_parameters); + descriptor->Run(raw_route, json_result); + return 200; + } +}; + +#endif // VIA_ROUTE_HPP diff --git a/server/api_grammar.hpp b/server/api_grammar.hpp index f9a22a522..7fd9986f1 100644 --- a/server/api_grammar.hpp +++ b/server/api_grammar.hpp @@ -66,7 +66,7 @@ template struct APIGrammar : qi::grammar> qi::lit("t") >> '=' >> qi::uint_[boost::bind(&HandlerT::addTimestamp, handler, ::_1)]; bearing = (-qi::lit('&')) >> qi::lit("b") >> '=' >> - qi::int_[boost::bind(&HandlerT::addBearing, handler, ::_1, ::_2, ::_3)]; + (qi::int_ >> -(qi::lit(',') >> qi::int_ | qi::attr(10)))[boost::bind(&HandlerT::addBearing, handler, ::_1, ::_2, ::_3)]; u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)]; uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >>