request polyline with precision of 5 or 6 positions (#3220)
This commit is contained in:
parent
1b03b8df6d
commit
f33180f092
@ -3,6 +3,7 @@
|
|||||||
- API:
|
- API:
|
||||||
- `osrm-datastore` now accepts the parameter `--max-wait` that specifies how long it waits before aquiring a shared memory lock by force
|
- `osrm-datastore` now accepts the parameter `--max-wait` that specifies how long it waits before aquiring a shared memory lock by force
|
||||||
- Shared memory now allows for multiple clients (multiple instances of libosrm on the same segment)
|
- Shared memory now allows for multiple clients (multiple instances of libosrm on the same segment)
|
||||||
|
- Polyline geometries can now be requested with precision 5 as well as with precision 6
|
||||||
- Profiles
|
- Profiles
|
||||||
- `restrictions` is now used for namespaced restrictions and restriction exceptions (e.g. `restriction:motorcar=` as well as `except=motorcar`)
|
- `restrictions` is now used for namespaced restrictions and restriction exceptions (e.g. `restriction:motorcar=` as well as `except=motorcar`)
|
||||||
- replaced lhs/rhs profiles by using test defined profiles
|
- replaced lhs/rhs profiles by using test defined profiles
|
||||||
|
35
docs/http.md
35
docs/http.md
@ -153,19 +153,19 @@ http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?number=3&b
|
|||||||
### Request
|
### Request
|
||||||
|
|
||||||
```
|
```
|
||||||
http://{server}/route/v1/{profile}/{coordinates}?alternatives={true|false}&steps={true|false}&geometries={polyline|geojson}&overview={full|simplified|false}&annotations={true|false}
|
http://{server}/route/v1/{profile}/{coordinates}?alternatives={true|false}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}
|
||||||
```
|
```
|
||||||
|
|
||||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||||
|
|
||||||
|Option |Values |Description |
|
|Option |Values |Description |
|
||||||
|------------|------------------------------------------|-------------------------------------------------------------------------------|
|
|------------|---------------------------------------------|-------------------------------------------------------------------------------|
|
||||||
|alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* |
|
|alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* |
|
||||||
|steps |`true`, `false` (default) |Return route steps for each route leg |
|
|steps |`true`, `false` (default) |Return route steps for each route leg |
|
||||||
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
||||||
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|
||||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||||
|continue_straight |`default` (default), `true`, `false`|Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. |
|
|continue_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. |
|
||||||
|
|
||||||
\* Please note that even if an alternative route is requested, a result cannot be guaranteed.
|
\* Please note that even if an alternative route is requested, a result cannot be guaranteed.
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ In case of error the following `code`s are supported in addition to the general
|
|||||||
|
|
||||||
| Type | Description |
|
| Type | Description |
|
||||||
|-------------------|-----------------|
|
|-------------------|-----------------|
|
||||||
| `NoRoute` | No route found. |
|
| `NoRoute` | No route found. |
|
||||||
|
|
||||||
All other fields might be undefined.
|
All other fields might be undefined.
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ The algorithm might not be able to match all points. Outliers are removed if the
|
|||||||
### Request
|
### Request
|
||||||
|
|
||||||
```
|
```
|
||||||
http://{server}/match/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|geojson}&overview={simplified|full|false}&annotations={true|false}
|
http://{server}/match/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|polyline6|geojson}&overview={simplified|full|false}&annotations={true|false}
|
||||||
```
|
```
|
||||||
|
|
||||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||||
@ -272,8 +272,8 @@ In addition to the [general options](#general-options) the following options are
|
|||||||
|Option |Values |Description |
|
|Option |Values |Description |
|
||||||
|------------|------------------------------------------------|------------------------------------------------------------------------------------------|
|
|------------|------------------------------------------------|------------------------------------------------------------------------------------------|
|
||||||
|steps |`true`, `false` (default) |Return route steps for each route |
|
|steps |`true`, `false` (default) |Return route steps for each route |
|
||||||
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|
||||||
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
||||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||||
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamp of the input location. Timestamps need to be monotonically increasing. |
|
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamp of the input location. Timestamps need to be monotonically increasing. |
|
||||||
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
|
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
|
||||||
@ -311,7 +311,7 @@ multiple trips for each connected component are returned.
|
|||||||
### Request
|
### Request
|
||||||
|
|
||||||
```
|
```
|
||||||
http://{server}/trip/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|geojson}&overview={simplified|full|false}&annotations={true|false}
|
http://{server}/trip/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|polyline6|geojson}&overview={simplified|full|false}&annotations={true|false}
|
||||||
```
|
```
|
||||||
|
|
||||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||||
@ -319,8 +319,8 @@ In addition to the [general options](#general-options) the following options are
|
|||||||
|Option |Values |Description |
|
|Option |Values |Description |
|
||||||
|------------|------------------------------------------------|---------------------------------------------------------------------------|
|
|------------|------------------------------------------------|---------------------------------------------------------------------------|
|
||||||
|steps |`true`, `false` (default) |Return route instructions for each trip |
|
|steps |`true`, `false` (default) |Return route instructions for each trip |
|
||||||
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
||||||
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|
||||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||||
|
|
||||||
### Response
|
### Response
|
||||||
@ -335,7 +335,7 @@ In case of error the following `code`s are supported in addition to the general
|
|||||||
|
|
||||||
| Type | Description |
|
| Type | Description |
|
||||||
|-------------------|---------------------|
|
|-------------------|---------------------|
|
||||||
| `NoTrips` | No trips found. |
|
| `NoTrips` | No trips found. |
|
||||||
|
|
||||||
All other fields might be undefined.
|
All other fields might be undefined.
|
||||||
|
|
||||||
@ -468,6 +468,7 @@ step.
|
|||||||
| geometries | |
|
| geometries | |
|
||||||
|------------|--------------------------------------------------------------------|
|
|------------|--------------------------------------------------------------------|
|
||||||
| polyline | [polyline](https://www.npmjs.com/package/polyline) with precision 5 in [latitude,longitude] encoding |
|
| polyline | [polyline](https://www.npmjs.com/package/polyline) with precision 5 in [latitude,longitude] encoding |
|
||||||
|
| polyline6 | [polyline](https://www.npmjs.com/package/polyline) with precision 6 in [latitude,longitude] encoding |
|
||||||
| geojson | [GeoJSON `LineString`](http://geojson.org/geojson-spec.html#linestring) or [GeoJSON `Point`](http://geojson.org/geojson-spec.html#point) if it is only one coordinate (not wrapped by a GeoJSON feature)|
|
| geojson | [GeoJSON `LineString`](http://geojson.org/geojson-spec.html#linestring) or [GeoJSON `Point`](http://geojson.org/geojson-spec.html#point) if it is only one coordinate (not wrapped by a GeoJSON feature)|
|
||||||
|
|
||||||
- `name`: The name of the way along which travel proceeds.
|
- `name`: The name of the way along which travel proceeds.
|
||||||
|
@ -90,7 +90,7 @@ module.exports = function () {
|
|||||||
|
|
||||||
if (headers.has('geometry')) {
|
if (headers.has('geometry')) {
|
||||||
if (json.matchings.length != 1) throw new Error('*** Checking geometry only supported for matchings with one subtrace');
|
if (json.matchings.length != 1) throw new Error('*** Checking geometry only supported for matchings with one subtrace');
|
||||||
geometry = json.matchings[0].geometry.coordinates;
|
geometry = json.matchings[0].geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.has('OSM IDs')) {
|
if (headers.has('OSM IDs')) {
|
||||||
@ -116,10 +116,13 @@ module.exports = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (headers.has('geometry')) {
|
if (headers.has('geometry')) {
|
||||||
if (this.queryParams['geometries'] === 'polyline')
|
if (this.queryParams['geometries'] === 'polyline') {
|
||||||
got.geometry = polyline.decode(geometry).toString();
|
got.geometry = polyline.decode(geometry).toString();
|
||||||
else
|
} else if (this.queryParams['geometries'] === 'polyline6') {
|
||||||
got.geometry = geometry;
|
got.geometry = polyline.decode(geometry,6).toString();
|
||||||
|
} else {
|
||||||
|
got.geometry = geometry.coordinates;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.has('OSM IDs')) {
|
if (headers.has('OSM IDs')) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
var polyline = require('polyline');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
function add(a, b) {
|
function add(a, b) {
|
||||||
@ -41,6 +42,16 @@ module.exports = function () {
|
|||||||
got.message = json.status_message;
|
got.message = json.status_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headers.has('geometry')) {
|
||||||
|
if (this.queryParams['geometries'] === 'polyline') {
|
||||||
|
got.geometry = polyline.decode(json.trips[0].geometry).toString();
|
||||||
|
} else if (this.queryParams['geometries'] === 'polyline6') {
|
||||||
|
got.geometry = polyline.decode(json.trips[0].geometry, 6).toString();
|
||||||
|
} else {
|
||||||
|
got.geometry = json.trips[0].geometry.coordinates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (headers.has('#')) {
|
if (headers.has('#')) {
|
||||||
// comment column
|
// comment column
|
||||||
got['#'] = row['#'];
|
got['#'] = row['#'];
|
||||||
|
@ -177,7 +177,7 @@ Feature: Basic Map Matching
|
|||||||
| trace | matchings | geometry |
|
| trace | matchings | geometry |
|
||||||
| efbc | efbc | 1,0.99964,1.000359,0.99964,1.000359,1,1.000718,1 |
|
| efbc | efbc | 1,0.99964,1.000359,0.99964,1.000359,1,1.000718,1 |
|
||||||
|
|
||||||
Scenario: Testbot - Geometry details
|
Scenario: Testbot - Geometry details using geojson
|
||||||
Given the query options
|
Given the query options
|
||||||
| overview | full |
|
| overview | full |
|
||||||
| geometries | geojson |
|
| geometries | geojson |
|
||||||
@ -197,7 +197,47 @@ Feature: Basic Map Matching
|
|||||||
| trace | matchings | geometry |
|
| trace | matchings | geometry |
|
||||||
| abd | abd | 1,1,1.000089,1,1.000089,1,1.000089,0.99991 |
|
| abd | abd | 1,1,1.000089,1,1.000089,1,1.000089,0.99991 |
|
||||||
|
|
||||||
Scenario: Testbot - Speed greater than speed threshhold, should split -- returns trace as abcd but should be split into ab,cd
|
Scenario: Testbot - Geometry details using polyline
|
||||||
|
Given the query options
|
||||||
|
| overview | full |
|
||||||
|
| geometries | polyline |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c
|
||||||
|
d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | no |
|
||||||
|
| bd | no |
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | matchings | geometry |
|
||||||
|
| abd | abd | 1,1,1,1.00009,1,1.00009,0.99991,1.00009 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Geometry details using polyline6
|
||||||
|
Given the query options
|
||||||
|
| overview | full |
|
||||||
|
| geometries | polyline6 |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c
|
||||||
|
d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| abc | no |
|
||||||
|
| bd | no |
|
||||||
|
|
||||||
|
When I match I should get
|
||||||
|
| trace | matchings | geometry |
|
||||||
|
| abd | abd | 1,1,1,1.000089,1,1.000089,0.99991,1.000089 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Speed greater than speed threshhold
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
Given the query options
|
Given the query options
|
||||||
| geometries | geojson |
|
| geometries | geojson |
|
||||||
@ -218,7 +258,7 @@ Feature: Basic Map Matching
|
|||||||
| trace | timestamps | matchings |
|
| trace | timestamps | matchings |
|
||||||
| abcd | 0 1 2 3 | ab,cd |
|
| abcd | 0 1 2 3 | ab,cd |
|
||||||
|
|
||||||
Scenario: Testbot - Speed less than speed threshhold, should not split
|
Scenario: Testbot - Speed less than speed threshhold
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
Given the query options
|
Given the query options
|
||||||
| geometries | geojson |
|
| geometries | geojson |
|
||||||
|
@ -122,3 +122,69 @@ Feature: Basic trip planning
|
|||||||
| waypoints | trips |
|
| waypoints | trips |
|
||||||
| a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a | |
|
| a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a | |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Trip with geometry details of geojson
|
||||||
|
Given the query options
|
||||||
|
| geometries | geojson |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| bc |
|
||||||
|
| cb |
|
||||||
|
| da |
|
||||||
|
|
||||||
|
When I plan a trip I should get
|
||||||
|
| waypoints | trips | durations | geometry |
|
||||||
|
| a,b,c,d | abcda | 7.6 | 1,1,1.000089,1,1,0.99991,1.000089,1,1,1,1.000089,0.99991,1,1 |
|
||||||
|
| d,b,c,a | dbcad | 7.6 | 1.000089,0.99991,1,1,1.000089,1,1,0.99991,1.000089,1,1,1,1.000089,0.99991 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Trip with geometry details of polyline
|
||||||
|
Given the query options
|
||||||
|
| geometries | polyline |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| bc |
|
||||||
|
| cb |
|
||||||
|
| da |
|
||||||
|
|
||||||
|
When I plan a trip I should get
|
||||||
|
| waypoints | trips | durations | geometry |
|
||||||
|
| a,b,c,d | abcda | 7.6 | 1,1,1,1.00009,0.99991,1,1,1.00009,1,1,0.99991,1.00009,1,1 |
|
||||||
|
| d,b,c,a | dbcad | 7.6 | 0.99991,1.00009,1,1,1,1.00009,0.99991,1,1,1.00009,1,1,0.99991,1.00009 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Trip with geometry details of polyline6
|
||||||
|
Given the query options
|
||||||
|
| geometries | polyline6 |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
| bc |
|
||||||
|
| cb |
|
||||||
|
| da |
|
||||||
|
|
||||||
|
When I plan a trip I should get
|
||||||
|
| waypoints | trips | durations | geometry |
|
||||||
|
| a,b,c,d | abcda | 7.6 | 1,1,1,1.000089,0.99991,1,1,1.000089,1,1,0.99991,1.000089,1,1 |
|
||||||
|
| d,b,c,a | dbcad | 7.6 | 0.99991,1.000089,1,1,1,1.000089,0.99991,1,1,1.000089,1,1,0.99991,1.000089 |
|
||||||
|
@ -42,9 +42,9 @@ std::string modeToString(const extractor::TravelMode mode);
|
|||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename ForwardIter> util::json::String makePolyline(ForwardIter begin, ForwardIter end)
|
template <unsigned POLYLINE_PRECISION, typename ForwardIter> util::json::String makePolyline(ForwardIter begin, ForwardIter end)
|
||||||
{
|
{
|
||||||
return {encodePolyline(begin, end)};
|
return {encodePolyline<POLYLINE_PRECISION>(begin, end)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ForwardIter>
|
template <typename ForwardIter>
|
||||||
|
@ -68,7 +68,12 @@ class RouteAPI : public BaseAPI
|
|||||||
{
|
{
|
||||||
if (parameters.geometries == RouteParameters::GeometriesType::Polyline)
|
if (parameters.geometries == RouteParameters::GeometriesType::Polyline)
|
||||||
{
|
{
|
||||||
return json::makePolyline(begin, end);
|
return json::makePolyline<100000>(begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameters.geometries == RouteParameters::GeometriesType::Polyline6)
|
||||||
|
{
|
||||||
|
return json::makePolyline<1000000>(begin, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
|
BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
|
||||||
@ -192,9 +197,17 @@ class RouteAPI : public BaseAPI
|
|||||||
if (parameters.geometries == RouteParameters::GeometriesType::Polyline)
|
if (parameters.geometries == RouteParameters::GeometriesType::Polyline)
|
||||||
{
|
{
|
||||||
return static_cast<util::json::Value>(
|
return static_cast<util::json::Value>(
|
||||||
json::makePolyline(leg_geometry.locations.begin() + step.geometry_begin,
|
json::makePolyline<100000>(leg_geometry.locations.begin() + step.geometry_begin,
|
||||||
leg_geometry.locations.begin() + step.geometry_end));
|
leg_geometry.locations.begin() + step.geometry_end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parameters.geometries == RouteParameters::GeometriesType::Polyline6)
|
||||||
|
{
|
||||||
|
return static_cast<util::json::Value>(
|
||||||
|
json::makePolyline<1000000>(leg_geometry.locations.begin() + step.geometry_begin,
|
||||||
|
leg_geometry.locations.begin() + step.geometry_end));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
|
BOOST_ASSERT(parameters.geometries == RouteParameters::GeometriesType::GeoJSON);
|
||||||
return static_cast<util::json::Value>(json::makeGeoJSONGeometry(
|
return static_cast<util::json::Value>(json::makeGeoJSONGeometry(
|
||||||
leg_geometry.locations.begin() + step.geometry_begin,
|
leg_geometry.locations.begin() + step.geometry_begin,
|
||||||
|
@ -45,7 +45,7 @@ namespace api
|
|||||||
* Holds member attributes:
|
* Holds member attributes:
|
||||||
* - steps: return route step for each route leg
|
* - steps: return route step for each route leg
|
||||||
* - alternatives: tries to find alternative routes
|
* - alternatives: tries to find alternative routes
|
||||||
* - geometries: route geometry encoded in Polyline or GeoJSON
|
* - geometries: route geometry encoded in Polyline, Polyline6 or GeoJSON
|
||||||
* - overview: adds overview geometry either Full, Simplified (according to highest zoom level) or
|
* - overview: adds overview geometry either Full, Simplified (according to highest zoom level) or
|
||||||
* False (not at all)
|
* False (not at all)
|
||||||
* - continue_straight: enable or disable continue_straight (disabled by default)
|
* - continue_straight: enable or disable continue_straight (disabled by default)
|
||||||
@ -58,6 +58,7 @@ struct RouteParameters : public BaseParameters
|
|||||||
enum class GeometriesType
|
enum class GeometriesType
|
||||||
{
|
{
|
||||||
Polyline,
|
Polyline,
|
||||||
|
Polyline6,
|
||||||
GeoJSON
|
GeoJSON
|
||||||
};
|
};
|
||||||
enum class OverviewType
|
enum class OverviewType
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -11,16 +13,44 @@ namespace osrm
|
|||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
constexpr double POLYLINE_PRECISION = 1e5;
|
constexpr double POLYLINE_DECODING_PRECISION = 1e5;
|
||||||
constexpr double COORDINATE_TO_POLYLINE = POLYLINE_PRECISION / COORDINATE_PRECISION;
|
constexpr double POLYLINE_TO_COORDINATE = COORDINATE_PRECISION / POLYLINE_DECODING_PRECISION;
|
||||||
constexpr double POLYLINE_TO_COORDINATE = COORDINATE_PRECISION / POLYLINE_PRECISION;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
std::string encode(std::vector<int> &numbers);
|
||||||
|
}
|
||||||
using CoordVectorForwardIter = std::vector<util::Coordinate>::const_iterator;
|
using CoordVectorForwardIter = std::vector<util::Coordinate>::const_iterator;
|
||||||
// Encodes geometry into polyline format.
|
// Encodes geometry into polyline format.
|
||||||
// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
||||||
std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter end);
|
|
||||||
|
template<unsigned POLYLINE_PRECISION=100000>
|
||||||
|
std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter end)
|
||||||
|
{
|
||||||
|
double coordinate_to_polyline = POLYLINE_PRECISION / COORDINATE_PRECISION;
|
||||||
|
auto size = std::distance(begin, end);
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> delta_numbers;
|
||||||
|
BOOST_ASSERT(size > 0);
|
||||||
|
delta_numbers.reserve((size - 1) * 2);
|
||||||
|
int current_lat = 0;
|
||||||
|
int current_lon = 0;
|
||||||
|
std::for_each(
|
||||||
|
begin, end, [&delta_numbers, ¤t_lat, ¤t_lon, coordinate_to_polyline](const util::Coordinate loc) {
|
||||||
|
const int lat_diff =
|
||||||
|
std::round(static_cast<int>(loc.lat) * coordinate_to_polyline) - current_lat;
|
||||||
|
const int lon_diff =
|
||||||
|
std::round(static_cast<int>(loc.lon) * coordinate_to_polyline) - current_lon;
|
||||||
|
delta_numbers.emplace_back(lat_diff);
|
||||||
|
delta_numbers.emplace_back(lon_diff);
|
||||||
|
current_lat += lat_diff;
|
||||||
|
current_lon += lon_diff;
|
||||||
|
});
|
||||||
|
return detail::encode(delta_numbers);
|
||||||
|
}
|
||||||
|
|
||||||
// Decodes geometry from polyline format
|
// Decodes geometry from polyline format
|
||||||
// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
||||||
|
@ -43,7 +43,8 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
|
|||||||
RouteParametersGrammar(qi::rule<Iterator, Signature> &root_rule_) : BaseGrammar(root_rule_)
|
RouteParametersGrammar(qi::rule<Iterator, Signature> &root_rule_) : BaseGrammar(root_rule_)
|
||||||
{
|
{
|
||||||
geometries_type.add("geojson", engine::api::RouteParameters::GeometriesType::GeoJSON)(
|
geometries_type.add("geojson", engine::api::RouteParameters::GeometriesType::GeoJSON)(
|
||||||
"polyline", engine::api::RouteParameters::GeometriesType::Polyline);
|
"polyline", engine::api::RouteParameters::GeometriesType::Polyline)(
|
||||||
|
"polyline6", engine::api::RouteParameters::GeometriesType::Polyline6);
|
||||||
|
|
||||||
overview_type.add("simplified", engine::api::RouteParameters::OverviewType::Simplified)(
|
overview_type.add("simplified", engine::api::RouteParameters::OverviewType::Simplified)(
|
||||||
"full", engine::api::RouteParameters::OverviewType::Full)(
|
"full", engine::api::RouteParameters::OverviewType::Full)(
|
||||||
|
@ -10,7 +10,7 @@ namespace osrm
|
|||||||
{
|
{
|
||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
namespace /*detail*/ // anonymous to keep TU local
|
namespace detail // anonymous to keep TU local
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string encode(int number_to_encode)
|
std::string encode(int number_to_encode)
|
||||||
@ -55,35 +55,6 @@ std::string encode(std::vector<int> &numbers)
|
|||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
} // anonymous ns
|
|
||||||
|
|
||||||
std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter end)
|
|
||||||
{
|
|
||||||
auto size = std::distance(begin, end);
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<int> delta_numbers;
|
|
||||||
BOOST_ASSERT(size > 0);
|
|
||||||
delta_numbers.reserve((size - 1) * 2);
|
|
||||||
int current_lat = 0;
|
|
||||||
int current_lon = 0;
|
|
||||||
std::for_each(
|
|
||||||
begin, end, [&delta_numbers, ¤t_lat, ¤t_lon](const util::Coordinate loc) {
|
|
||||||
const int lat_diff =
|
|
||||||
std::round(static_cast<int>(loc.lat) * detail::COORDINATE_TO_POLYLINE) -
|
|
||||||
current_lat;
|
|
||||||
const int lon_diff =
|
|
||||||
std::round(static_cast<int>(loc.lon) * detail::COORDINATE_TO_POLYLINE) -
|
|
||||||
current_lon;
|
|
||||||
delta_numbers.emplace_back(lat_diff);
|
|
||||||
delta_numbers.emplace_back(lon_diff);
|
|
||||||
current_lat += lat_diff;
|
|
||||||
current_lon += lon_diff;
|
|
||||||
});
|
|
||||||
return encode(delta_numbers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<util::Coordinate> decodePolyline(const std::string &geometry_string)
|
std::vector<util::Coordinate> decodePolyline(const std::string &geometry_string)
|
||||||
|
@ -44,4 +44,47 @@ BOOST_AUTO_TEST_CASE(decode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(encode)
|
||||||
|
{
|
||||||
|
// Coordinates; these would be the coordinates we give the loc parameter,
|
||||||
|
// e.g. loc=10.00,10.0&loc=10.01,10.1...
|
||||||
|
util::Coordinate coord1(util::FloatLongitude{10.0}, util::FloatLatitude{10.00});
|
||||||
|
util::Coordinate coord2(util::FloatLongitude{10.1}, util::FloatLatitude{10.01});
|
||||||
|
util::Coordinate coord3(util::FloatLongitude{10.2}, util::FloatLatitude{10.02});
|
||||||
|
util::Coordinate coord4(util::FloatLongitude{10.3}, util::FloatLatitude{10.03});
|
||||||
|
util::Coordinate coord5(util::FloatLongitude{10.4}, util::FloatLatitude{10.04});
|
||||||
|
|
||||||
|
// Test polyline string for the 5 coordinates
|
||||||
|
const std::string polyline = "_c`|@_c`|@o}@_pRo}@_pRo}@_pRo}@_pR";
|
||||||
|
|
||||||
|
// Put the test coordinates into the vector for comparison
|
||||||
|
std::vector<util::Coordinate> cmp_coords = {coord1, coord2, coord3, coord4, coord5};
|
||||||
|
|
||||||
|
const auto encodedPolyline = encodePolyline<100000>(cmp_coords.begin(), cmp_coords.end());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(encodedPolyline, polyline);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(encode6)
|
||||||
|
{
|
||||||
|
// Coordinates; these would be the coordinates we give the loc parameter,
|
||||||
|
// e.g. loc=10.00,10.0&loc=10.01,10.1...
|
||||||
|
util::Coordinate coord1(util::FloatLongitude{10.0}, util::FloatLatitude{10.00});
|
||||||
|
util::Coordinate coord2(util::FloatLongitude{10.1}, util::FloatLatitude{10.01});
|
||||||
|
util::Coordinate coord3(util::FloatLongitude{10.2}, util::FloatLatitude{10.02});
|
||||||
|
util::Coordinate coord4(util::FloatLongitude{10.3}, util::FloatLatitude{10.03});
|
||||||
|
util::Coordinate coord5(util::FloatLongitude{10.4}, util::FloatLatitude{10.04});
|
||||||
|
|
||||||
|
// Test polyline string for the 6 coordinates
|
||||||
|
const std::string polyline = "_gjaR_gjaR_pR_ibE_pR_ibE_pR_ibE_pR_ibE";
|
||||||
|
|
||||||
|
// Put the test coordinates into the vector for comparison
|
||||||
|
std::vector<util::Coordinate> cmp_coords = {coord1, coord2, coord3, coord4, coord5};
|
||||||
|
|
||||||
|
const auto encodedPolyline = encodePolyline<1000000>(cmp_coords.begin(), cmp_coords.end());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(encodedPolyline, polyline);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
Loading…
Reference in New Issue
Block a user