Merge pull request #1766 from Project-OSRM/feature/bearing_selection
Add bearing support to all plugins, add optional range to bearing parameter.
This commit is contained in:
		
						commit
						13ceeb191c
					
				| @ -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<int, boost::optional<int>> &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<int> 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) | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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                      | | ||||
|  | ||||
| @ -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<int, boost::optional<int>> &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<std::string> hints; | ||||
|     std::vector<unsigned> timestamps; | ||||
|     std::vector<int> bearings; | ||||
|     std::vector<std::pair<const int,const boost::optional<int>>> bearings; | ||||
|     std::vector<bool> uturns; | ||||
|     std::vector<FixedPointCoordinate> coordinates; | ||||
| }; | ||||
|  | ||||
| @ -75,6 +75,13 @@ template <class DataFacadeT> 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<unsigned>(max_locations_distance_table), | ||||
| @ -94,8 +101,10 @@ template <class DataFacadeT> 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())); | ||||
|         } | ||||
|  | ||||
| @ -94,7 +94,7 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin | ||||
|     } | ||||
| 
 | ||||
|     bool getCandidates(const std::vector<FixedPointCoordinate> &input_coords, | ||||
|                       const std::vector<int> &input_bearings, | ||||
|                       const std::vector<std::pair<const int,const boost::optional<int>>> &input_bearings, | ||||
|                       const double gps_precision, | ||||
|                       std::vector<double> &sub_trace_lengths, | ||||
|                       osrm::matching::CandidateLists &candidates_lists) | ||||
| @ -130,8 +130,8 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin | ||||
| 
 | ||||
|             std::vector<std::pair<PhantomNode, double>> 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); | ||||
|  | ||||
| @ -58,11 +58,21 @@ template <class DataFacadeT> 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<std::size_t>(route_parameters.num_results); | ||||
|         std::vector<PhantomNode> 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<int>(number_of_results)); | ||||
|                                                         static_cast<int>(number_of_results), bearing, range); | ||||
| 
 | ||||
|         if (phantom_node_vector.empty() || !phantom_node_vector.front().is_valid()) | ||||
|         { | ||||
|  | ||||
| @ -76,6 +76,7 @@ template <class DataFacadeT> 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<std::size_t>(0, route_parameters.coordinates.size())) | ||||
| @ -92,8 +93,10 @@ template <class DataFacadeT> 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 DataFacadeT> 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); | ||||
|  | ||||
| @ -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 <osrm/json_container.hpp> | ||||
| 
 | ||||
| #include <cstdlib> | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin | ||||
| { | ||||
|   private: | ||||
|     DescriptorTable descriptor_table; | ||||
|     std::string descriptor_string; | ||||
|     std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr; | ||||
|     DataFacadeT *facade; | ||||
| 
 | ||||
|   public: | ||||
|     explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade) | ||||
|     { | ||||
|         search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(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> phantom_node_pair_list(route_parameters.coordinates.size()); | ||||
|         const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); | ||||
| 
 | ||||
|         for (const auto i : osrm::irange<std::size_t>(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<PhantomNode> 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<BaseDescriptor<DataFacadeT>> descriptor; | ||||
|         switch (descriptor_table.get_id(route_parameters.output_format)) | ||||
|         { | ||||
|         case 1: | ||||
|             descriptor = osrm::make_unique<GPXDescriptor<DataFacadeT>>(facade); | ||||
|             break; | ||||
|         // case 2:
 | ||||
|         //      descriptor = osrm::make_unique<GEOJSONDescriptor<DataFacadeT>>();
 | ||||
|         //      break;
 | ||||
|         default: | ||||
|             descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(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 <osrm/json_container.hpp> | ||||
| 
 | ||||
| #include <cstdlib> | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin | ||||
| { | ||||
|   private: | ||||
|     DescriptorTable descriptor_table; | ||||
|     std::string descriptor_string; | ||||
|     std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr; | ||||
|     DataFacadeT *facade; | ||||
| 
 | ||||
|   public: | ||||
|     explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade) | ||||
|     { | ||||
|         search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(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> phantom_node_pair_list(route_parameters.coordinates.size()); | ||||
|         const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); | ||||
| 
 | ||||
|         for (const auto i : osrm::irange<std::size_t>(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<PhantomNode> 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<BaseDescriptor<DataFacadeT>> descriptor; | ||||
|         switch (descriptor_table.get_id(route_parameters.output_format)) | ||||
|         { | ||||
|         case 1: | ||||
|             descriptor = osrm::make_unique<GPXDescriptor<DataFacadeT>>(facade); | ||||
|             break; | ||||
|         // case 2:
 | ||||
|         //      descriptor = osrm::make_unique<GEOJSONDescriptor<DataFacadeT>>();
 | ||||
|         //      break;
 | ||||
|         default: | ||||
|             descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         descriptor->SetConfig(route_parameters); | ||||
|         descriptor->Run(raw_route, json_result); | ||||
|         return 200; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| #endif // VIA_ROUTE_HPP
 | ||||
|  | ||||
| @ -66,7 +66,7 @@ template <typename Iterator, class HandlerT> struct APIGrammar : qi::grammar<Ite | ||||
|         timestamp = (-qi::lit('&')) >> 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") >> '=' >> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user