diff --git a/algorithms/polyline_compressor.cpp b/algorithms/polyline_compressor.cpp index d5fd5828b..0db75dcc6 100644 --- a/algorithms/polyline_compressor.cpp +++ b/algorithms/polyline_compressor.cpp @@ -88,3 +88,41 @@ PolylineCompressor::get_encoded_string(const std::vector &po } return encode_vector(delta_numbers); } + +std::vector PolylineCompressor::decode_string(const std::string &geometry_string) const +{ + std::vector new_coordinates; + int index = 0, len = geometry_string.size(); + int lat = 0, lng = 0; + + while (index < len) + { + int b, shift = 0, result = 0; + do + { + b = geometry_string.at(index++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); + lat += dlat; + + shift = 0; + result = 0; + do + { + b = geometry_string.at(index++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); + lng += dlng; + + FixedPointCoordinate p; + p.lat = COORDINATE_PRECISION * (((double) lat / 1E6)); + p.lon = COORDINATE_PRECISION * (((double) lng / 1E6)); + new_coordinates.push_back(p); + } + + return new_coordinates; +} diff --git a/algorithms/polyline_compressor.hpp b/algorithms/polyline_compressor.hpp index 933ac7afa..a148200ca 100644 --- a/algorithms/polyline_compressor.hpp +++ b/algorithms/polyline_compressor.hpp @@ -30,6 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct SegmentInformation; +#include + #include #include @@ -42,6 +44,8 @@ class PolylineCompressor public: std::string get_encoded_string(const std::vector &polyline) const; + + std::vector decode_string(const std::string &geometry_string) const; }; #endif /* POLYLINECOMPRESSOR_H_ */ diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp index 3b615e2c4..86b955358 100644 --- a/data_structures/route_parameters.cpp +++ b/data_structures/route_parameters.cpp @@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include "../algorithms/polyline_compressor.hpp" + RouteParameters::RouteParameters() : zoom_level(18), print_instructions(false), alternate_route(true), geometry(true), compression(true), deprecatedAPI(false), uturn_default(false), classify(false), @@ -131,3 +133,9 @@ void RouteParameters::addCoordinate( static_cast(COORDINATE_PRECISION * boost::fusion::at_c<0>(received_coordinates)), static_cast(COORDINATE_PRECISION * boost::fusion::at_c<1>(received_coordinates))); } + +void RouteParameters::getCoordinatesFromGeometry(const std::string geometry_string) +{ + PolylineCompressor pc; + coordinates = pc.decode_string(geometry_string); +} diff --git a/include/osrm/route_parameters.hpp b/include/osrm/route_parameters.hpp index 9babbd763..bc413d73b 100644 --- a/include/osrm/route_parameters.hpp +++ b/include/osrm/route_parameters.hpp @@ -78,6 +78,8 @@ struct RouteParameters void setCompressionFlag(const bool flag); void addCoordinate(const boost::fusion::vector &received_coordinates); + + void getCoordinatesFromGeometry(const std::string geometry_string); short zoom_level; bool print_instructions; diff --git a/server/api_grammar.hpp b/server/api_grammar.hpp index a629cfbf7..470954f74 100644 --- a/server/api_grammar.hpp +++ b/server/api_grammar.hpp @@ -42,7 +42,7 @@ template struct APIGrammar : qi::grammar> -(uturns); query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | timestamp | u | cmp | language | instruction | geometry | alt_route | old_API | num_results | - matching_beta | gps_precision | classify)); + matching_beta | gps_precision | classify | locs)); zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; @@ -83,17 +83,20 @@ template struct APIGrammar : qi::grammar> qi::lit("classify") >> '=' >> qi::bool_[boost::bind(&HandlerT::setClassify, handler, ::_1)]; + locs = (-qi::lit('&')) >> qi::lit("locs") >> '=' >> + stringforPolyline[boost::bind(&HandlerT::getCoordinatesFromGeometry, handler, ::_1)]; string = +(qi::char_("a-zA-Z")); stringwithDot = +(qi::char_("a-zA-Z0-9_.-")); stringwithPercent = +(qi::char_("a-zA-Z0-9_.-") | qi::char_('[') | qi::char_(']') | (qi::char_('%') >> qi::char_("0-9A-Z") >> qi::char_("0-9A-Z"))); + stringforPolyline = +(qi::char_("a-zA-Z0-9_.-[]{}@?|\\%~`^")); } qi::rule api_call, query; qi::rule service, zoom, output, string, jsonp, checksum, location, hint, timestamp, stringwithDot, stringwithPercent, language, instruction, geometry, cmp, alt_route, u, - uturns, old_API, num_results, matching_beta, gps_precision, classify; + uturns, old_API, num_results, matching_beta, gps_precision, classify, locs, stringforPolyline; HandlerT *handler; }; diff --git a/unit_tests/algorithms/geometry_string.cpp b/unit_tests/algorithms/geometry_string.cpp new file mode 100644 index 000000000..035b3217c --- /dev/null +++ b/unit_tests/algorithms/geometry_string.cpp @@ -0,0 +1,74 @@ +/* + +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. + +*/ + +#include +#include + +#include "../../algorithms/polyline_compressor.hpp" +#include "../../data_structures/coordinate_calculation.hpp" + +#include + +#include +#include + +BOOST_AUTO_TEST_CASE(geometry_string) +{ + // Polyline string for the 5 coordinates + const std::string polyline = "_gjaR_gjaR_pR_ibE_pR_ibE_pR_ibE_pR_ibE"; + PolylineCompressor pc; + std::vector coords = pc.decode_string(polyline); + + // Test coordinates; these would be the coordinates we give the loc parameter, + // e.g. loc=10.00,10.0&loc=10.01,10.1... + FixedPointCoordinate coord1(10.00 * COORDINATE_PRECISION, 10.0 * COORDINATE_PRECISION); + FixedPointCoordinate coord2(10.01 * COORDINATE_PRECISION, 10.1 * COORDINATE_PRECISION); + FixedPointCoordinate coord3(10.02 * COORDINATE_PRECISION, 10.2 * COORDINATE_PRECISION); + FixedPointCoordinate coord4(10.03 * COORDINATE_PRECISION, 10.3 * COORDINATE_PRECISION); + FixedPointCoordinate coord5(10.04 * COORDINATE_PRECISION, 10.4 * COORDINATE_PRECISION); + + // Put the test coordinates into the vector for comparison + std::vector cmp_coords; + cmp_coords.emplace_back(coord1); + cmp_coords.emplace_back(coord2); + cmp_coords.emplace_back(coord3); + cmp_coords.emplace_back(coord4); + cmp_coords.emplace_back(coord5); + + BOOST_CHECK_EQUAL(cmp_coords.size(), coords.size()); + + for(unsigned i = 0; i < cmp_coords.size(); ++i) + { + const double cmp1_lat = coords.at(i).lat; + const double cmp2_lat = cmp_coords.at(i).lat; + BOOST_CHECK_CLOSE(cmp1_lat, cmp2_lat, 0.0001); + + const double cmp1_lon = coords.at(i).lon; + const double cmp2_lon = cmp_coords.at(i).lon; + BOOST_CHECK_CLOSE(cmp1_lon, cmp2_lon, 0.0001); + } +}