Compare commits
7 Commits
master
...
v5.21.0-cu
Author | SHA1 | Date | |
---|---|---|---|
|
210908dbe6 | ||
|
6b9006f6e7 | ||
|
ca55521c87 | ||
|
67e99c9809 | ||
|
05647adcc6 | ||
|
6c37b71046 | ||
|
cb2a46b8d9 |
@ -35,3 +35,28 @@ Feature: Car - Allowed start/end modes
|
|||||||
| from | to | route | modes |
|
| from | to | route | modes |
|
||||||
| 1 | 2 | ab,ab | driving,driving |
|
| 1 | 2 | ab,ab | driving,driving |
|
||||||
| 2 | 1 | ab,ab | driving,driving |
|
| 2 | 1 | ab,ab | driving,driving |
|
||||||
|
|
||||||
|
Scenario: Car - URL override of non-startpoints
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 b c 2 d
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the query options
|
||||||
|
| snapping | any |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | access |
|
||||||
|
| ab | service | private |
|
||||||
|
| bc | primary | |
|
||||||
|
| cd | service | private |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | 2 | c |
|
||||||
|
| 1 | 59.1 | 35.1 |
|
||||||
|
| b | 35.1 | 11.1 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| 1 | 2 | ab,bc,cd |
|
||||||
|
| 2 | 1 | cd,bc,ab |
|
||||||
|
168
features/testbot/stoppage.feature
Normal file
168
features/testbot/stoppage.feature
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
@routing @maxspeed @testbot
|
||||||
|
Feature: Testbot - Acceleration profiles
|
||||||
|
|
||||||
|
Background: Use specific speeds
|
||||||
|
Given the profile "testbot"
|
||||||
|
|
||||||
|
Scenario: Testbot - No stoppage penalties
|
||||||
|
Given a grid size of 10 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | time | distance |
|
||||||
|
| a | b | ab,ab | 3.6s | 59.9m |
|
||||||
|
| a | 1 | ab,ab | 0.6s | 10m |
|
||||||
|
| a | 2 | ab,ab | 1.2s | 20m |
|
||||||
|
| a | 3 | ab,ab | 1.8s | 30m |
|
||||||
|
| a | 4 | ab,ab | 2.4s | 40m |
|
||||||
|
| a | 5 | ab,ab | 3s | 50m |
|
||||||
|
| 5 | b | ab,ab | 0.6s | 9.9m |
|
||||||
|
| 4 | b | ab,ab | 1.2s | 19.9m |
|
||||||
|
| 3 | b | ab,ab | 1.8s | 29.9m |
|
||||||
|
| 2 | b | ab,ab | 2.4s | 39.9m |
|
||||||
|
| 1 | b | ab,ab | 3s | 49.9m |
|
||||||
|
| 1 | 2 | ab,ab | 0.6s | 10m |
|
||||||
|
| 1 | 3 | ab,ab | 1.2s | 20m |
|
||||||
|
| 1 | 4 | ab,ab | 1.8s | 30m |
|
||||||
|
| 1 | 5 | ab,ab | 2.4s | 40m |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||||
|
| a | 0 | 0.6 | 1.2 | 1.8 | 2.4 | 3 | 3.6 |
|
||||||
|
| 1 | 0.8 | 0 | 0.6 | 1.2 | 1.8 | 2.4 | 3 |
|
||||||
|
| 2 | 1.6 | 0.8 | 0 | 0.6 | 1.2 | 1.8 | 2.4 |
|
||||||
|
| 3 | 2.4 | 1.6 | 0.8 | 0 | 0.6 | 1.2 | 1.8 |
|
||||||
|
| 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 | 0.6 | 1.2 |
|
||||||
|
| 5 | 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 | 0.6 |
|
||||||
|
| b | 4.8 | 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - No stoppage points, tiny grid size
|
||||||
|
Given a grid size of 1 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 6 7 8 9 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | b |
|
||||||
|
| a | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 | 0.3 | 0.4 | 0.4 | 0.5 | 0.6 |
|
||||||
|
| 1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 | 0.3 | 0.4 | 0.4 | 0.5 | 0.6 |
|
||||||
|
| 2 | 0.1 | 0.1 | 0 | 0 | 0.1 | 0.2 | 0.2 | 0.3 | 0.3 | 0.4 | 0.5 |
|
||||||
|
| 3 | 0.2 | 0.2 | 0 | 0 | 0.1 | 0.2 | 0.2 | 0.3 | 0.3 | 0.4 | 0.5 |
|
||||||
|
| 4 | 0.3 | 0.3 | 0.2 | 0.1 | 0 | 0.1 | 0.1 | 0.2 | 0.2 | 0.3 | 0.4 |
|
||||||
|
| 5 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 |
|
||||||
|
| 6 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 |
|
||||||
|
| 7 | 0.5 | 0.5 | 0.4 | 0.3 | 0.2 | 0.1 | 0.1 | 0 | 0 | 0.1 | 0.2 |
|
||||||
|
| 8 | 0.6 | 0.6 | 0.5 | 0.4 | 0.3 | 0.2 | 0.2 | 0 | 0 | 0.1 | 0.2 |
|
||||||
|
| 9 | 0.7 | 0.7 | 0.6 | 0.5 | 0.4 | 0.3 | 0.3 | 0.2 | 0.1 | 0 | 0.1 |
|
||||||
|
| b | 0.8 | 0.8 | 0.7 | 0.6 | 0.5 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - No stoppage points, tiny grid size
|
||||||
|
Given a grid size of 1 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 6 7 8 9 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| stoppage_penalty | 1.85,15 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | b |
|
||||||
|
| a | 0 | 1.4 | 2 | 2.5 | 2.9 | 3.2 | 3.6 | 3.8 | 4.1 | 4.4 | 4.6 |
|
||||||
|
| 1 | 1.4 | 0 | 1.4 | 2 | 2.5 | 2.9 | 3.2 | 3.6 | 3.8 | 4.1 | 4.4 |
|
||||||
|
| 2 | 2 | 1.4 | 0 | 1.4 | 2 | 2.5 | 2.9 | 3.2 | 3.6 | 3.8 | 4.1 |
|
||||||
|
| 3 | 2.5 | 2 | 1.4 | 0 | 1.4 | 2 | 2.5 | 2.9 | 3.2 | 3.6 | 3.8 |
|
||||||
|
| 4 | 2.9 | 2.5 | 2 | 1.4 | 0 | 1.4 | 2 | 2.5 | 2.9 | 3.2 | 3.6 |
|
||||||
|
| 5 | 3.2 | 2.9 | 2.5 | 2 | 1.4 | 0 | 1.4 | 2 | 2.5 | 2.9 | 3.2 |
|
||||||
|
| 6 | 3.6 | 3.2 | 2.9 | 2.5 | 2 | 1.4 | 0 | 1.4 | 2 | 2.5 | 2.9 |
|
||||||
|
| 7 | 3.8 | 3.6 | 3.2 | 2.9 | 2.5 | 2 | 1.4 | 0 | 1.4 | 2 | 2.5 |
|
||||||
|
| 8 | 4.1 | 3.8 | 3.6 | 3.2 | 2.9 | 2.5 | 2 | 1.4 | 0 | 1.4 | 2 |
|
||||||
|
| 9 | 4.4 | 4.1 | 3.8 | 3.6 | 3.2 | 2.9 | 2.5 | 2 | 1.4 | 0 | 1.4 |
|
||||||
|
| b | 4.6 | 4.4 | 4.1 | 3.8 | 3.6 | 3.2 | 2.9 | 2.5 | 2 | 1.4 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Use stoppage penalty at waypoints
|
||||||
|
Given a grid size of 10 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| stoppage_penalty | 1.85,15 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||||
|
| a | 0 | 4.6 | 6.5 | 8 | 9.3 | 10.4 | 11.3 |
|
||||||
|
| 1 | 4.6 | 0 | 4.6 | 6.5 | 8 | 9.3 | 10.3 |
|
||||||
|
| 2 | 6.5 | 4.6 | 0 | 4.6 | 6.5 | 8 | 9.2 |
|
||||||
|
| 3 | 8 | 6.5 | 4.6 | 0 | 4.6 | 6.5 | 8 |
|
||||||
|
| 4 | 9.3 | 8 | 6.5 | 4.6 | 0 | 4.6 | 6.5 |
|
||||||
|
| 5 | 10.4 | 9.3 | 8 | 6.5 | 4.6 | 0 | 4.6 |
|
||||||
|
| b | 11.3 | 10.3 | 9.2 | 8 | 6.5 | 4.6 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Long distance grid with no penalty
|
||||||
|
Given a grid size of 1000 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||||
|
| a | 0 | 59.9 | 119.9 | 179.9 | 239.9 | 299.9 | 359.9 |
|
||||||
|
| 1 | 79.9 | 0 | 60 | 120 | 180 | 240 | 300 |
|
||||||
|
| 2 | 159.9 | 80 | 0 | 60 | 120 | 180 | 240 |
|
||||||
|
| 3 | 239.9 | 160 | 80 | 0 | 60 | 120 | 180 |
|
||||||
|
| 4 | 319.9 | 240 | 160 | 80 | 0 | 60 | 120 |
|
||||||
|
| 5 | 399.9 | 320 | 240 | 160 | 80 | 0 | 60 |
|
||||||
|
| b | 479.9 | 400 | 320 | 240 | 160 | 80 | 0 |
|
||||||
|
|
||||||
|
Scenario: Long distance grid
|
||||||
|
Given a grid size of 1000 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| stoppage_penalty | 1.85,15 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||||
|
| a | 0 | 68.9 | 128.9 | 188.9 | 248.9 | 308.9 | 368.9 |
|
||||||
|
| 1 | 86.6 | 0 | 69 | 129 | 189 | 249 | 309 |
|
||||||
|
| 2 | 166.6 | 86.7 | 0 | 69 | 129 | 189 | 249 |
|
||||||
|
| 3 | 246.6 | 166.7 | 86.7 | 0 | 69 | 129 | 189 |
|
||||||
|
| 4 | 326.6 | 246.7 | 166.7 | 86.7 | 0 | 69 | 129 |
|
||||||
|
| 5 | 406.6 | 326.7 | 246.7 | 166.7 | 86.7 | 0 | 69 |
|
||||||
|
| b | 486.6 | 406.7 | 326.7 | 246.7 | 166.7 | 86.7 | 0 |
|
@ -63,6 +63,13 @@ namespace api
|
|||||||
*/
|
*/
|
||||||
struct BaseParameters
|
struct BaseParameters
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum class SnappingType
|
||||||
|
{
|
||||||
|
Default,
|
||||||
|
Any
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<util::Coordinate> coordinates;
|
std::vector<util::Coordinate> coordinates;
|
||||||
std::vector<boost::optional<Hint>> hints;
|
std::vector<boost::optional<Hint>> hints;
|
||||||
std::vector<boost::optional<double>> radiuses;
|
std::vector<boost::optional<double>> radiuses;
|
||||||
@ -73,21 +80,34 @@ struct BaseParameters
|
|||||||
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
||||||
bool generate_hints = true;
|
bool generate_hints = true;
|
||||||
|
|
||||||
|
SnappingType snapping = SnappingType::Default;
|
||||||
|
double min_stoppage_penalty = INVALID_MINIMUM_STOPPAGE_PENALTY;
|
||||||
|
double max_stoppage_penalty = INVALID_MAXIMUM_STOPPAGE_PENALTY;
|
||||||
|
|
||||||
BaseParameters(const std::vector<util::Coordinate> coordinates_ = {},
|
BaseParameters(const std::vector<util::Coordinate> coordinates_ = {},
|
||||||
const std::vector<boost::optional<Hint>> hints_ = {},
|
const std::vector<boost::optional<Hint>> hints_ = {},
|
||||||
std::vector<boost::optional<double>> radiuses_ = {},
|
std::vector<boost::optional<double>> radiuses_ = {},
|
||||||
std::vector<boost::optional<Bearing>> bearings_ = {},
|
std::vector<boost::optional<Bearing>> bearings_ = {},
|
||||||
std::vector<boost::optional<Approach>> approaches_ = {},
|
std::vector<boost::optional<Approach>> approaches_ = {},
|
||||||
bool generate_hints_ = true,
|
bool generate_hints_ = true,
|
||||||
std::vector<std::string> exclude = {})
|
std::vector<std::string> exclude = {},
|
||||||
|
const SnappingType snapping_ = SnappingType::Default,
|
||||||
|
double min_stoppage_penalty_ = INVALID_MINIMUM_STOPPAGE_PENALTY,
|
||||||
|
double max_stoppage_penalty_ = INVALID_MAXIMUM_STOPPAGE_PENALTY)
|
||||||
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
|
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
|
||||||
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_)
|
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_),
|
||||||
|
snapping(snapping_), min_stoppage_penalty(min_stoppage_penalty_),
|
||||||
|
max_stoppage_penalty(max_stoppage_penalty_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME add validation for invalid bearing values
|
// FIXME add validation for invalid bearing values
|
||||||
bool IsValid() const
|
bool IsValid() const
|
||||||
{
|
{
|
||||||
|
if (min_stoppage_penalty <= 0 || max_stoppage_penalty <= 0 ||
|
||||||
|
min_stoppage_penalty > max_stoppage_penalty)
|
||||||
|
return false;
|
||||||
|
|
||||||
return (hints.empty() || hints.size() == coordinates.size()) &&
|
return (hints.empty() || hints.size() == coordinates.size()) &&
|
||||||
(bearings.empty() || bearings.size() == coordinates.size()) &&
|
(bearings.empty() || bearings.size() == coordinates.size()) &&
|
||||||
(radiuses.empty() || radiuses.size() == coordinates.size()) &&
|
(radiuses.empty() || radiuses.size() == coordinates.size()) &&
|
||||||
@ -103,8 +123,8 @@ struct BaseParameters
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace api
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // ROUTE_PARAMETERS_HPP
|
#endif // ROUTE_PARAMETERS_HPP
|
||||||
|
@ -78,7 +78,6 @@ struct TableParameters : public BaseParameters
|
|||||||
};
|
};
|
||||||
|
|
||||||
AnnotationsType annotations = AnnotationsType::Duration;
|
AnnotationsType annotations = AnnotationsType::Duration;
|
||||||
|
|
||||||
double scale_factor = 1;
|
double scale_factor = 1;
|
||||||
|
|
||||||
TableParameters() = default;
|
TableParameters() = default;
|
||||||
@ -113,7 +112,6 @@ struct TableParameters : public BaseParameters
|
|||||||
destinations{std::move(destinations_)}, fallback_speed{fallback_speed_},
|
destinations{std::move(destinations_)}, fallback_speed{fallback_speed_},
|
||||||
fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_},
|
fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_},
|
||||||
scale_factor{scale_factor_}
|
scale_factor{scale_factor_}
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,8 +164,8 @@ inline TableParameters::AnnotationsType &operator|=(TableParameters::Annotations
|
|||||||
{
|
{
|
||||||
return lhs = lhs | rhs;
|
return lhs = lhs | rhs;
|
||||||
}
|
}
|
||||||
}
|
} // namespace api
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // ENGINE_API_TABLE_PARAMETERS_HPP
|
#endif // ENGINE_API_TABLE_PARAMETERS_HPP
|
||||||
|
@ -384,50 +384,84 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
input_coordinate, max_results, max_distance, bearing, bearing_range, approach);
|
input_coordinate, max_results, max_distance, bearing, bearing_range, approach);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
const util::Coordinate input_coordinate,
|
||||||
const Approach approach) const override final
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double minimum_stoppage_penalty,
|
||||||
|
const double maximum_stoppage_penalty) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
input_coordinate, approach);
|
input_coordinate,
|
||||||
|
approach,
|
||||||
|
use_all_edges,
|
||||||
|
minimum_stoppage_penalty,
|
||||||
|
maximum_stoppage_penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
const util::Coordinate input_coordinate,
|
||||||
const double max_distance,
|
const double max_distance,
|
||||||
const Approach approach) const override final
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double minimum_stoppage_penalty,
|
||||||
|
const double maximum_stoppage_penalty) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
input_coordinate, max_distance, approach);
|
input_coordinate,
|
||||||
|
max_distance,
|
||||||
|
approach,
|
||||||
|
use_all_edges,
|
||||||
|
minimum_stoppage_penalty,
|
||||||
|
maximum_stoppage_penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
const util::Coordinate input_coordinate,
|
||||||
const double max_distance,
|
const double max_distance,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const override final
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double minimum_stoppage_penalty,
|
||||||
|
const double maximum_stoppage_penalty) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
input_coordinate, max_distance, bearing, bearing_range, approach);
|
input_coordinate,
|
||||||
|
max_distance,
|
||||||
|
bearing,
|
||||||
|
bearing_range,
|
||||||
|
approach,
|
||||||
|
use_all_edges,
|
||||||
|
minimum_stoppage_penalty,
|
||||||
|
maximum_stoppage_penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
const util::Coordinate input_coordinate,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const override final
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double minimum_stoppage_penalty,
|
||||||
|
const double maximum_stoppage_penalty) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
input_coordinate, bearing, bearing_range, approach);
|
input_coordinate,
|
||||||
|
bearing,
|
||||||
|
bearing_range,
|
||||||
|
approach,
|
||||||
|
use_all_edges,
|
||||||
|
minimum_stoppage_penalty,
|
||||||
|
maximum_stoppage_penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint32_t GetCheckSum() const override final { return m_check_sum; }
|
std::uint32_t GetCheckSum() const override final { return m_check_sum; }
|
||||||
|
@ -157,24 +157,36 @@ class BaseDataFacade
|
|||||||
const double max_distance,
|
const double max_distance,
|
||||||
const Approach approach) const = 0;
|
const Approach approach) const = 0;
|
||||||
|
|
||||||
virtual std::pair<PhantomNode, PhantomNode>
|
virtual std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
const util::Coordinate input_coordinate,
|
||||||
const Approach approach) const = 0;
|
const Approach approach,
|
||||||
virtual std::pair<PhantomNode, PhantomNode>
|
const bool use_all_edges,
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
const double minimum_stoppage_penalty,
|
||||||
const double max_distance,
|
const double maximum_stoppage_penalty) const = 0;
|
||||||
const Approach approach) const = 0;
|
virtual std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
virtual std::pair<PhantomNode, PhantomNode>
|
const util::Coordinate input_coordinate,
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
const double max_distance,
|
||||||
const double max_distance,
|
const Approach approach,
|
||||||
const int bearing,
|
const bool use_all_edges,
|
||||||
const int bearing_range,
|
const double minimum_stoppage_penalty,
|
||||||
const Approach approach) const = 0;
|
const double maximum_stoppage_penalty) const = 0;
|
||||||
virtual std::pair<PhantomNode, PhantomNode>
|
virtual std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
const util::Coordinate input_coordinate,
|
||||||
const int bearing,
|
const double max_distance,
|
||||||
const int bearing_range,
|
const int bearing,
|
||||||
const Approach approach) const = 0;
|
const int bearing_range,
|
||||||
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double minimum_stoppage_penalty,
|
||||||
|
const double maximum_stoppage_penalty) const = 0;
|
||||||
|
virtual std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
|
const util::Coordinate input_coordinate,
|
||||||
|
const int bearing,
|
||||||
|
const int bearing_range,
|
||||||
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double minimum_stoppage_penalty,
|
||||||
|
const double maximum_stoppage_penalty) const = 0;
|
||||||
|
|
||||||
virtual bool HasLaneData(const EdgeID id) const = 0;
|
virtual bool HasLaneData(const EdgeID id) const = 0;
|
||||||
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
|
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
|
||||||
|
@ -205,18 +205,25 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const double max_distance,
|
const double max_distance,
|
||||||
const Approach approach) const
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double min_stoppage_penalty,
|
||||||
|
const double max_stoppage_penalty) const
|
||||||
{
|
{
|
||||||
bool has_small_component = false;
|
bool has_small_component = false;
|
||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
[this,
|
||||||
const CandidateSegment &segment) {
|
approach,
|
||||||
|
&input_coordinate,
|
||||||
|
&has_big_component,
|
||||||
|
&has_small_component,
|
||||||
|
&use_all_edges](const CandidateSegment &segment) {
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
const auto valid_edges = HasValidEdge(segment);
|
const auto valid_edges = HasValidEdge(segment, use_all_edges);
|
||||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, admissible_segments);
|
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||||
@ -243,27 +250,39 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(results.size() == 1 || results.size() == 2);
|
BOOST_ASSERT(results.size() == 1 || results.size() == 2);
|
||||||
return std::make_pair(MakePhantomNode(input_coordinate, results.front()).phantom_node,
|
return std::make_pair(
|
||||||
MakePhantomNode(input_coordinate, results.back()).phantom_node);
|
MakePhantomNode(
|
||||||
|
input_coordinate, results.front(), min_stoppage_penalty, max_stoppage_penalty)
|
||||||
|
.phantom_node,
|
||||||
|
MakePhantomNode(
|
||||||
|
input_coordinate, results.back(), min_stoppage_penalty, max_stoppage_penalty)
|
||||||
|
.phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the nearest phantom node. If this phantom node is not from a big component
|
// Returns the nearest phantom node. If this phantom node is not from a big component
|
||||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const Approach approach) const
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double min_stoppage_penalty,
|
||||||
|
const double max_stoppage_penalty) const
|
||||||
{
|
{
|
||||||
bool has_small_component = false;
|
bool has_small_component = false;
|
||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
[this,
|
||||||
const CandidateSegment &segment) {
|
approach,
|
||||||
|
&input_coordinate,
|
||||||
|
&has_big_component,
|
||||||
|
&has_small_component,
|
||||||
|
&use_all_edges](const CandidateSegment &segment) {
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
|
|
||||||
const auto valid_edges = HasValidEdge(segment);
|
const auto valid_edges = HasValidEdge(segment, use_all_edges);
|
||||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, admissible_segments);
|
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||||
@ -288,8 +307,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(results.size() == 1 || results.size() == 2);
|
BOOST_ASSERT(results.size() == 1 || results.size() == 2);
|
||||||
return std::make_pair(MakePhantomNode(input_coordinate, results.front()).phantom_node,
|
return std::make_pair(
|
||||||
MakePhantomNode(input_coordinate, results.back()).phantom_node);
|
MakePhantomNode(
|
||||||
|
input_coordinate, results.front(), min_stoppage_penalty, max_stoppage_penalty)
|
||||||
|
.phantom_node,
|
||||||
|
MakePhantomNode(
|
||||||
|
input_coordinate, results.back(), min_stoppage_penalty, max_stoppage_penalty)
|
||||||
|
.phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the nearest phantom node. If this phantom node is not from a big component
|
// Returns the nearest phantom node. If this phantom node is not from a big component
|
||||||
@ -298,7 +322,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double min_stoppage_penalty,
|
||||||
|
const double max_stoppage_penalty) const
|
||||||
{
|
{
|
||||||
bool has_small_component = false;
|
bool has_small_component = false;
|
||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
@ -310,12 +337,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
bearing,
|
bearing,
|
||||||
bearing_range,
|
bearing_range,
|
||||||
&has_big_component,
|
&has_big_component,
|
||||||
&has_small_component](const CandidateSegment &segment) {
|
&has_small_component,
|
||||||
|
&use_all_edges](const CandidateSegment &segment) {
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
|
||||||
|
|
||||||
if (use_segment)
|
if (use_segment)
|
||||||
{
|
{
|
||||||
@ -345,8 +373,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(results.size() > 0);
|
BOOST_ASSERT(results.size() > 0);
|
||||||
return std::make_pair(MakePhantomNode(input_coordinate, results.front()).phantom_node,
|
return std::make_pair(
|
||||||
MakePhantomNode(input_coordinate, results.back()).phantom_node);
|
MakePhantomNode(
|
||||||
|
input_coordinate, results.front(), min_stoppage_penalty, max_stoppage_penalty)
|
||||||
|
.phantom_node,
|
||||||
|
MakePhantomNode(
|
||||||
|
input_coordinate, results.back(), min_stoppage_penalty, max_stoppage_penalty)
|
||||||
|
.phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the nearest phantom node. If this phantom node is not from a big component
|
// Returns the nearest phantom node. If this phantom node is not from a big component
|
||||||
@ -356,7 +389,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
const double max_distance,
|
const double max_distance,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const
|
const Approach approach,
|
||||||
|
const bool use_all_edges,
|
||||||
|
const double min_stoppage_penalty,
|
||||||
|
const double max_stoppage_penalty) const
|
||||||
{
|
{
|
||||||
bool has_small_component = false;
|
bool has_small_component = false;
|
||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
@ -368,12 +404,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
bearing,
|
bearing,
|
||||||
bearing_range,
|
bearing_range,
|
||||||
&has_big_component,
|
&has_big_component,
|
||||||
&has_small_component](const CandidateSegment &segment) {
|
&has_small_component,
|
||||||
|
&use_all_edges](const CandidateSegment &segment) {
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
|
||||||
|
|
||||||
if (use_segment)
|
if (use_segment)
|
||||||
{
|
{
|
||||||
@ -405,8 +442,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(results.size() > 0);
|
BOOST_ASSERT(results.size() > 0);
|
||||||
return std::make_pair(MakePhantomNode(input_coordinate, results.front()).phantom_node,
|
return std::make_pair(
|
||||||
MakePhantomNode(input_coordinate, results.back()).phantom_node);
|
MakePhantomNode(
|
||||||
|
input_coordinate, results.front(), min_stoppage_penalty, max_stoppage_penalty)
|
||||||
|
.phantom_node,
|
||||||
|
MakePhantomNode(
|
||||||
|
input_coordinate, results.back(), min_stoppage_penalty, max_stoppage_penalty)
|
||||||
|
.phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -424,8 +466,11 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
return distance_and_phantoms;
|
return distance_and_phantoms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove stoppage penalty as its not needed here anymore
|
||||||
PhantomNodeWithDistance MakePhantomNode(const util::Coordinate input_coordinate,
|
PhantomNodeWithDistance MakePhantomNode(const util::Coordinate input_coordinate,
|
||||||
const EdgeData &data) const
|
const EdgeData &data,
|
||||||
|
const double min_stoppage_penalty = 0,
|
||||||
|
const double max_stoppage_penalty = 0) const
|
||||||
{
|
{
|
||||||
util::Coordinate point_on_segment;
|
util::Coordinate point_on_segment;
|
||||||
double ratio;
|
double ratio;
|
||||||
@ -464,16 +509,21 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
forward_durations.begin() + data.fwd_segment_position,
|
forward_durations.begin() + data.fwd_segment_position,
|
||||||
EdgeDuration{0});
|
EdgeDuration{0});
|
||||||
|
|
||||||
EdgeDistance forward_distance_offset = 0;
|
// For measuring distance from begin up to end
|
||||||
// Sum up the distance from the start to the fwd_segment_position
|
const auto appx_distance = [this](decltype(forward_geometry.begin()) begin,
|
||||||
for (auto current = forward_geometry.begin();
|
decltype(forward_geometry.begin()) end) {
|
||||||
current < forward_geometry.begin() + data.fwd_segment_position;
|
EdgeDistance dist = 0;
|
||||||
++current)
|
for (; begin != end; ++begin)
|
||||||
{
|
{
|
||||||
forward_distance_offset += util::coordinate_calculation::fccApproximateDistance(
|
dist += util::coordinate_calculation::fccApproximateDistance(
|
||||||
datafacade.GetCoordinateOfNode(*current),
|
datafacade.GetCoordinateOfNode(*begin),
|
||||||
datafacade.GetCoordinateOfNode(*std::next(current)));
|
datafacade.GetCoordinateOfNode(*std::next(begin)));
|
||||||
}
|
}
|
||||||
|
return dist;
|
||||||
|
};
|
||||||
|
|
||||||
|
EdgeDistance forward_distance_offset = appx_distance(
|
||||||
|
forward_geometry.begin(), forward_geometry.begin() + data.fwd_segment_position);
|
||||||
|
|
||||||
BOOST_ASSERT(data.fwd_segment_position <
|
BOOST_ASSERT(data.fwd_segment_position <
|
||||||
std::distance(forward_durations.begin(), forward_durations.end()));
|
std::distance(forward_durations.begin(), forward_durations.end()));
|
||||||
@ -494,16 +544,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
reverse_durations.end() - data.fwd_segment_position - 1,
|
reverse_durations.end() - data.fwd_segment_position - 1,
|
||||||
EdgeDuration{0});
|
EdgeDuration{0});
|
||||||
|
|
||||||
EdgeDistance reverse_distance_offset = 0;
|
EdgeDistance reverse_distance_offset =
|
||||||
// Sum up the distance from just after the fwd_segment_position to the end
|
appx_distance(forward_geometry.begin() + data.fwd_segment_position + 1,
|
||||||
for (auto current = forward_geometry.begin() + data.fwd_segment_position + 1;
|
std::prev(forward_geometry.end()));
|
||||||
current != std::prev(forward_geometry.end());
|
|
||||||
++current)
|
|
||||||
{
|
|
||||||
reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance(
|
|
||||||
datafacade.GetCoordinateOfNode(*current),
|
|
||||||
datafacade.GetCoordinateOfNode(*std::next(current)));
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeWeight reverse_weight =
|
EdgeWeight reverse_weight =
|
||||||
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1];
|
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1];
|
||||||
@ -513,16 +556,43 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
point_on_segment,
|
point_on_segment,
|
||||||
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1)));
|
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1)));
|
||||||
|
|
||||||
|
// We may end up adding a stoppage penalty
|
||||||
|
double forward_speed = 0;
|
||||||
|
double reverse_speed = 0;
|
||||||
|
auto total_distance = 0;
|
||||||
|
auto penalty_range = max_stoppage_penalty - min_stoppage_penalty;
|
||||||
ratio = std::min(1.0, std::max(0.0, ratio));
|
ratio = std::min(1.0, std::max(0.0, ratio));
|
||||||
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
|
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
|
||||||
{
|
{
|
||||||
forward_weight = static_cast<EdgeWeight>(forward_weight * ratio);
|
forward_weight = static_cast<EdgeWeight>(forward_weight * ratio);
|
||||||
forward_duration = static_cast<EdgeDuration>(forward_duration * ratio);
|
forward_duration = static_cast<EdgeDuration>(forward_duration * ratio);
|
||||||
|
// Stoppage penalty based on speed
|
||||||
|
if (data.forward_segment_id.enabled && penalty_range > 0)
|
||||||
|
{
|
||||||
|
total_distance =
|
||||||
|
appx_distance(forward_geometry.begin(), std::prev(forward_geometry.end()));
|
||||||
|
const auto total_duration = std::accumulate(
|
||||||
|
forward_durations.begin(), forward_durations.end(), EdgeDuration{0});
|
||||||
|
forward_speed = total_distance / (total_duration * 0.1);
|
||||||
|
reverse_speed = forward_speed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (data.reverse_segment_id.id != SPECIAL_SEGMENTID)
|
if (data.reverse_segment_id.id != SPECIAL_SEGMENTID)
|
||||||
{
|
{
|
||||||
reverse_weight -= static_cast<EdgeWeight>(reverse_weight * ratio);
|
reverse_weight -= static_cast<EdgeWeight>(reverse_weight * ratio);
|
||||||
reverse_duration -= static_cast<EdgeDuration>(reverse_duration * ratio);
|
reverse_duration -= static_cast<EdgeDuration>(reverse_duration * ratio);
|
||||||
|
// Stoppage penalty based on speed
|
||||||
|
if (data.reverse_segment_id.enabled && penalty_range > 0)
|
||||||
|
{
|
||||||
|
if (total_distance == 0)
|
||||||
|
total_distance =
|
||||||
|
appx_distance(forward_geometry.begin(), std::prev(forward_geometry.end()));
|
||||||
|
const auto total_duration = std::accumulate(
|
||||||
|
reverse_durations.begin(), reverse_durations.end(), EdgeDuration{0});
|
||||||
|
reverse_speed = total_distance / (total_duration * 0.1);
|
||||||
|
if (forward_speed == 0)
|
||||||
|
forward_speed = reverse_speed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check phantom node segments validity
|
// check phantom node segments validity
|
||||||
@ -553,6 +623,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
reverse_duration,
|
reverse_duration,
|
||||||
forward_duration_offset,
|
forward_duration_offset,
|
||||||
reverse_duration_offset,
|
reverse_duration_offset,
|
||||||
|
static_cast<float>((forward_speed + reverse_speed) / 2.0),
|
||||||
is_forward_valid_source,
|
is_forward_valid_source,
|
||||||
is_forward_valid_target,
|
is_forward_valid_target,
|
||||||
is_reverse_valid_source,
|
is_reverse_valid_source,
|
||||||
@ -703,7 +774,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
const CoordinateList &coordinates;
|
const CoordinateList &coordinates;
|
||||||
DataFacadeT &datafacade;
|
DataFacadeT &datafacade;
|
||||||
};
|
};
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -122,7 +122,7 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
|
|||||||
[](const NamedSegment &segment) { return segment.name_id; });
|
[](const NamedSegment &segment) { return segment.name_id; });
|
||||||
return summary;
|
return summary;
|
||||||
}
|
}
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
||||||
const std::vector<PathData> &route_data,
|
const std::vector<PathData> &route_data,
|
||||||
@ -166,7 +166,7 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
|||||||
// `forward_duration`: duration of (d,t)
|
// `forward_duration`: duration of (d,t)
|
||||||
// `forward_offset`: duration of (c, d)
|
// `forward_offset`: duration of (c, d)
|
||||||
// path_data will have entries for (s,b), (b, c), (c, d) but (d, t) is only
|
// path_data will have entries for (s,b), (b, c), (c, d) but (d, t) is only
|
||||||
// caputed by the phantom node. So we need to add the target duration here.
|
// captured by the phantom node. So we need to add the target duration here.
|
||||||
// On local segments, the target duration is already part of the duration, however.
|
// On local segments, the target duration is already part of the duration, however.
|
||||||
|
|
||||||
duration = duration + target_duration;
|
duration = duration + target_duration;
|
||||||
@ -182,6 +182,9 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
|||||||
duration = std::max(0, duration);
|
duration = std::max(0, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add start and stop penalties to the duration to simulate accel/deceleration
|
||||||
|
//
|
||||||
|
|
||||||
std::string summary;
|
std::string summary;
|
||||||
if (needs_summary)
|
if (needs_summary)
|
||||||
{
|
{
|
||||||
|
@ -63,11 +63,11 @@ struct Hint
|
|||||||
friend std::ostream &operator<<(std::ostream &, const Hint &);
|
friend std::ostream &operator<<(std::ostream &, const Hint &);
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(Hint) == 80 + 4, "Hint is bigger than expected");
|
static_assert(sizeof(Hint) == sizeof(PhantomNode) + 4, "Hint is bigger than expected");
|
||||||
constexpr std::size_t ENCODED_HINT_SIZE = 112;
|
constexpr std::size_t ENCODED_HINT_SIZE = 120;
|
||||||
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
||||||
"ENCODED_HINT_SIZE does not match size of Hint");
|
"ENCODED_HINT_SIZE does not match size of Hint");
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,14 +44,15 @@ namespace engine
|
|||||||
struct PhantomNode
|
struct PhantomNode
|
||||||
{
|
{
|
||||||
PhantomNode()
|
PhantomNode()
|
||||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
: forward_segment_id{SPECIAL_SEGMENTID, false}, reverse_segment_id{SPECIAL_SEGMENTID,
|
||||||
reverse_segment_id{SPECIAL_SEGMENTID, false}, forward_weight(INVALID_EDGE_WEIGHT),
|
false},
|
||||||
reverse_weight(INVALID_EDGE_WEIGHT), forward_weight_offset(0), reverse_weight_offset(0),
|
forward_weight(INVALID_EDGE_WEIGHT), reverse_weight(INVALID_EDGE_WEIGHT),
|
||||||
|
forward_weight_offset(0), reverse_weight_offset(0),
|
||||||
forward_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE),
|
forward_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE),
|
||||||
forward_distance_offset(0), reverse_distance_offset(0),
|
forward_distance_offset(0), reverse_distance_offset(0),
|
||||||
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
|
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
|
||||||
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0),
|
forward_duration_offset(0), reverse_duration_offset(0), speed_approximation(0),
|
||||||
is_valid_forward_source{false}, is_valid_forward_target{false},
|
fwd_segment_position(0), is_valid_forward_source{false}, is_valid_forward_target{false},
|
||||||
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
|
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -69,13 +70,13 @@ struct PhantomNode
|
|||||||
return reverse_weight_offset + reverse_weight;
|
return reverse_weight_offset + reverse_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeWeight GetForwardDuration() const
|
EdgeDuration GetForwardDuration() const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(forward_segment_id.enabled);
|
BOOST_ASSERT(forward_segment_id.enabled);
|
||||||
return forward_duration + forward_duration_offset;
|
return forward_duration + forward_duration_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeWeight GetReverseDuration() const
|
EdgeDuration GetReverseDuration() const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(reverse_segment_id.enabled);
|
BOOST_ASSERT(reverse_segment_id.enabled);
|
||||||
return reverse_duration + reverse_duration_offset;
|
return reverse_duration + reverse_duration_offset;
|
||||||
@ -109,8 +110,9 @@ struct PhantomNode
|
|||||||
|
|
||||||
bool IsValid(const unsigned number_of_nodes) const
|
bool IsValid(const unsigned number_of_nodes) const
|
||||||
{
|
{
|
||||||
return location.IsValid() && ((forward_segment_id.id < number_of_nodes) ||
|
return location.IsValid() &&
|
||||||
(reverse_segment_id.id < number_of_nodes)) &&
|
((forward_segment_id.id < number_of_nodes) ||
|
||||||
|
(reverse_segment_id.id < number_of_nodes)) &&
|
||||||
((forward_weight != INVALID_EDGE_WEIGHT) ||
|
((forward_weight != INVALID_EDGE_WEIGHT) ||
|
||||||
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
||||||
((forward_duration != MAXIMAL_EDGE_DURATION) ||
|
((forward_duration != MAXIMAL_EDGE_DURATION) ||
|
||||||
@ -163,10 +165,11 @@ struct PhantomNode
|
|||||||
EdgeDistance reverse_distance,
|
EdgeDistance reverse_distance,
|
||||||
EdgeDistance forward_distance_offset,
|
EdgeDistance forward_distance_offset,
|
||||||
EdgeDistance reverse_distance_offset,
|
EdgeDistance reverse_distance_offset,
|
||||||
EdgeWeight forward_duration,
|
EdgeDuration forward_duration,
|
||||||
EdgeWeight reverse_duration,
|
EdgeDuration reverse_duration,
|
||||||
EdgeWeight forward_duration_offset,
|
EdgeDuration forward_duration_offset,
|
||||||
EdgeWeight reverse_duration_offset,
|
EdgeDuration reverse_duration_offset,
|
||||||
|
EdgeDistance speed_approximation,
|
||||||
bool is_valid_forward_source,
|
bool is_valid_forward_source,
|
||||||
bool is_valid_forward_target,
|
bool is_valid_forward_target,
|
||||||
bool is_valid_reverse_source,
|
bool is_valid_reverse_source,
|
||||||
@ -182,8 +185,9 @@ struct PhantomNode
|
|||||||
reverse_distance_offset{reverse_distance_offset}, forward_duration{forward_duration},
|
reverse_distance_offset{reverse_distance_offset}, forward_duration{forward_duration},
|
||||||
reverse_duration{reverse_duration}, forward_duration_offset{forward_duration_offset},
|
reverse_duration{reverse_duration}, forward_duration_offset{forward_duration_offset},
|
||||||
reverse_duration_offset{reverse_duration_offset},
|
reverse_duration_offset{reverse_duration_offset},
|
||||||
component{component.id, component.is_tiny}, location{location},
|
speed_approximation{speed_approximation}, component{component.id, component.is_tiny},
|
||||||
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
|
location{location}, input_location{input_location},
|
||||||
|
fwd_segment_position{other.fwd_segment_position},
|
||||||
is_valid_forward_source{is_valid_forward_source},
|
is_valid_forward_source{is_valid_forward_source},
|
||||||
is_valid_forward_target{is_valid_forward_target},
|
is_valid_forward_target{is_valid_forward_target},
|
||||||
is_valid_reverse_source{is_valid_reverse_source},
|
is_valid_reverse_source{is_valid_reverse_source},
|
||||||
@ -201,10 +205,12 @@ struct PhantomNode
|
|||||||
EdgeDistance reverse_distance;
|
EdgeDistance reverse_distance;
|
||||||
EdgeDistance forward_distance_offset; // TODO: try to remove -> requires path unpacking changes
|
EdgeDistance forward_distance_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
EdgeDistance reverse_distance_offset; // TODO: try to remove -> requires path unpacking changes
|
EdgeDistance reverse_distance_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
EdgeWeight forward_duration;
|
EdgeDuration forward_duration;
|
||||||
EdgeWeight reverse_duration;
|
EdgeDuration reverse_duration;
|
||||||
EdgeWeight forward_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
EdgeDuration forward_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
EdgeWeight reverse_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
EdgeDuration reverse_duration_offset; // TODO: try to remove -> requires path unpacking changes
|
||||||
|
EdgeDistance speed_approximation; // m/s
|
||||||
|
|
||||||
ComponentID component;
|
ComponentID component;
|
||||||
|
|
||||||
util::Coordinate location; // this is the coordinate of x
|
util::Coordinate location; // this is the coordinate of x
|
||||||
@ -219,7 +225,7 @@ struct PhantomNode
|
|||||||
unsigned short bearing : 12;
|
unsigned short bearing : 12;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(PhantomNode) == 80, "PhantomNode has more padding then expected");
|
static_assert(sizeof(PhantomNode) == 84, "PhantomNode has more padding then expected");
|
||||||
|
|
||||||
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
||||||
|
|
||||||
@ -234,7 +240,7 @@ struct PhantomNodes
|
|||||||
PhantomNode source_phantom;
|
PhantomNode source_phantom;
|
||||||
PhantomNode target_phantom;
|
PhantomNode target_phantom;
|
||||||
};
|
};
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // PHANTOM_NODES_H
|
#endif // PHANTOM_NODES_H
|
||||||
|
@ -270,6 +270,7 @@ class BasePlugin
|
|||||||
const bool use_bearings = !parameters.bearings.empty();
|
const bool use_bearings = !parameters.bearings.empty();
|
||||||
const bool use_radiuses = !parameters.radiuses.empty();
|
const bool use_radiuses = !parameters.radiuses.empty();
|
||||||
const bool use_approaches = !parameters.approaches.empty();
|
const bool use_approaches = !parameters.approaches.empty();
|
||||||
|
const bool use_all_edges = parameters.snapping == api::BaseParameters::SnappingType::Any;
|
||||||
|
|
||||||
BOOST_ASSERT(parameters.IsValid());
|
BOOST_ASSERT(parameters.IsValid());
|
||||||
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||||
@ -296,7 +297,10 @@ class BasePlugin
|
|||||||
*parameters.radiuses[i],
|
*parameters.radiuses[i],
|
||||||
parameters.bearings[i]->bearing,
|
parameters.bearings[i]->bearing,
|
||||||
parameters.bearings[i]->range,
|
parameters.bearings[i]->range,
|
||||||
approach);
|
approach,
|
||||||
|
use_all_edges,
|
||||||
|
parameters.min_stoppage_penalty,
|
||||||
|
parameters.max_stoppage_penalty);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -305,7 +309,10 @@ class BasePlugin
|
|||||||
parameters.coordinates[i],
|
parameters.coordinates[i],
|
||||||
parameters.bearings[i]->bearing,
|
parameters.bearings[i]->bearing,
|
||||||
parameters.bearings[i]->range,
|
parameters.bearings[i]->range,
|
||||||
approach);
|
approach,
|
||||||
|
use_all_edges,
|
||||||
|
parameters.min_stoppage_penalty,
|
||||||
|
parameters.max_stoppage_penalty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -314,13 +321,22 @@ class BasePlugin
|
|||||||
{
|
{
|
||||||
phantom_node_pairs[i] =
|
phantom_node_pairs[i] =
|
||||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
parameters.coordinates[i], *parameters.radiuses[i], approach);
|
parameters.coordinates[i],
|
||||||
|
*parameters.radiuses[i],
|
||||||
|
approach,
|
||||||
|
use_all_edges,
|
||||||
|
parameters.min_stoppage_penalty,
|
||||||
|
parameters.max_stoppage_penalty);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
phantom_node_pairs[i] =
|
phantom_node_pairs[i] =
|
||||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
parameters.coordinates[i], approach);
|
parameters.coordinates[i],
|
||||||
|
approach,
|
||||||
|
use_all_edges,
|
||||||
|
parameters.min_stoppage_penalty,
|
||||||
|
parameters.max_stoppage_penalty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
81
include/extractor/speed_profile.hpp
Normal file
81
include/extractor/speed_profile.hpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include "util/typedefs.h"
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr int 5_MINUTE_BUCKETS_PER_WEEK = 2016;
|
||||||
|
constexpr int 1_HOUR_BUCKETS_PER_WEEK = 168;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a simple piecewise linear function
|
||||||
|
* (https://en.wikipedia.org/wiki/Piecewise_linear_function)
|
||||||
|
* in the form of a regularly spaced set of buckets.
|
||||||
|
* Assumes that the spacing between buckets is equal.
|
||||||
|
*/
|
||||||
|
template <typename DataType, int BUCKETCOUNT> struct PiecewiseLinearFunction
|
||||||
|
{
|
||||||
|
std::array<DataType, BUCKETCOUNT> sample;
|
||||||
|
|
||||||
|
inline DataType getAt(float position)
|
||||||
|
{
|
||||||
|
// Range check
|
||||||
|
assert(position >= 0);
|
||||||
|
assert(position < BUCKETCOUNT - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
PiecewiseLinearFunction<DataType, BUCKETCOUNT>
|
||||||
|
merge(PiecewiseLinearFunction<DataType, BUCKETCOUNT> &other, float offset)
|
||||||
|
{
|
||||||
|
PiecewiseLinearFunction result;
|
||||||
|
|
||||||
|
for (int i = 0; i < BUCKETCOUNT; i++)
|
||||||
|
{
|
||||||
|
for (int j = offset; j < BUCKETCOUNT + offset; j++)
|
||||||
|
{
|
||||||
|
|
||||||
|
result.sample[i] = sample[i] + other.sample[j % BUCKETCOUNT];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents variances in the default `.duration` of an edge
|
||||||
|
* over the space of a week.
|
||||||
|
*/
|
||||||
|
struct WeeklySpeedProfile
|
||||||
|
{
|
||||||
|
using Multiplier = std::uint8_t;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PiecewiseLinearFunction<Multiplier, 1_HOUR_BUCKETS_PER_WEEK> fn;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SpeedProfile() : min(0), max(0) { multipliers.fill(0); }
|
||||||
|
SpeedProfile(const std::array<Multiplier, BUCKETS> &other)
|
||||||
|
{
|
||||||
|
fn.samples = other;
|
||||||
|
min = std::min(samples);
|
||||||
|
max = std::max(samples);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EdgeDuration adjust(const EdgeDuration &original, const int bucket) const
|
||||||
|
{
|
||||||
|
// Treat Multiplier as an 8-bit fixed-point value.
|
||||||
|
EdgeDuration new_value = (original * multipliers[bucket]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EdgeDuration min(const EdgeDuration original) const {}
|
||||||
|
|
||||||
|
inline EdgeDuration max(const EdgeDuration original) const {}
|
||||||
|
|
||||||
|
duration = m * e1 + m2 * e2
|
||||||
|
};
|
||||||
|
} // namespace extractor
|
||||||
|
} // namespace osrm
|
@ -692,6 +692,80 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->Has(Nan::New("snapping").ToLocalChecked()))
|
||||||
|
{
|
||||||
|
v8::Local<v8::Value> snapping = obj->Get(Nan::New("snapping").ToLocalChecked());
|
||||||
|
if (snapping.IsEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!snapping->IsString())
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Snapping must be a string: [default, any]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const Nan::Utf8String snapping_utf8str(snapping);
|
||||||
|
std::string snapping_str{*snapping_utf8str, *snapping_utf8str + snapping_utf8str.length()};
|
||||||
|
|
||||||
|
if (snapping_str == "default")
|
||||||
|
{
|
||||||
|
params->snapping = osrm::RouteParameters::SnappingType::Default;
|
||||||
|
}
|
||||||
|
else if (snapping_str == "any")
|
||||||
|
{
|
||||||
|
params->snapping = osrm::RouteParameters::SnappingType::Any;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Nan::ThrowError("'snapping' param must be one of [default, any]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj->Has(Nan::New("stoppage_penalty").ToLocalChecked()))
|
||||||
|
{
|
||||||
|
v8::Local<v8::Value> stoppage_penalty =
|
||||||
|
obj->Get(Nan::New("stoppage_penalty").ToLocalChecked());
|
||||||
|
if (stoppage_penalty.IsEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!stoppage_penalty->IsArray())
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Stoppage penalty must be an array of 2 numbers [min,max]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto stoppage_penalty_array = v8::Local<v8::Array>::Cast(stoppage_penalty);
|
||||||
|
|
||||||
|
if (stoppage_penalty_array->Length() != 2)
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Stoppage penalty must be an array of 2 numbers [min,max]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stoppage_penalty_array->Get(0)->IsNumber() ||
|
||||||
|
!stoppage_penalty_array->Get(1)->IsNumber())
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Stoppage penalty must be an array of 2 numbers [min,max]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto min = static_cast<short>(stoppage_penalty_array->Get(0)->NumberValue());
|
||||||
|
const auto max = static_cast<short>(stoppage_penalty_array->Get(1)->NumberValue());
|
||||||
|
|
||||||
|
if (min < 0 || max < 0)
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Stoppage penalty min/max can't be less than zero");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (max < min)
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Stoppage penalty max must be larger than min");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
params->max_stoppage_penalty = max;
|
||||||
|
params->min_stoppage_penalty = min;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace
|
|||||||
{
|
{
|
||||||
namespace ph = boost::phoenix;
|
namespace ph = boost::phoenix;
|
||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
template <typename T, char... Fmt> struct no_trailing_dot_policy : qi::real_policies<T>
|
template <typename T, char... Fmt> struct no_trailing_dot_policy : qi::real_policies<T>
|
||||||
{
|
{
|
||||||
@ -135,6 +135,16 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
},
|
},
|
||||||
qi::_1)];
|
qi::_1)];
|
||||||
|
|
||||||
|
stoppage_rule = qi::lit("stoppage_penalty=") >
|
||||||
|
(qi::double_ > ',' > qi::double_)[ph::bind(
|
||||||
|
[](engine::api::BaseParameters ¶ms, double min, double max) {
|
||||||
|
params.min_stoppage_penalty = min;
|
||||||
|
params.max_stoppage_penalty = max;
|
||||||
|
},
|
||||||
|
qi::_r1,
|
||||||
|
qi::_1,
|
||||||
|
qi::_2)];
|
||||||
|
|
||||||
query_rule =
|
query_rule =
|
||||||
((location_rule % ';') | polyline_rule |
|
((location_rule % ';') | polyline_rule |
|
||||||
polyline6_rule)[ph::bind(&engine::api::BaseParameters::coordinates, qi::_r1) = qi::_1];
|
polyline6_rule)[ph::bind(&engine::api::BaseParameters::coordinates, qi::_r1) = qi::_1];
|
||||||
@ -162,6 +172,13 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
(-approach_type %
|
(-approach_type %
|
||||||
';')[ph::bind(&engine::api::BaseParameters::approaches, qi::_r1) = qi::_1];
|
';')[ph::bind(&engine::api::BaseParameters::approaches, qi::_r1) = qi::_1];
|
||||||
|
|
||||||
|
snapping_type.add("default", engine::api::BaseParameters::SnappingType::Default)(
|
||||||
|
"any", engine::api::BaseParameters::SnappingType::Any);
|
||||||
|
|
||||||
|
snapping_rule =
|
||||||
|
qi::lit("snapping=") >
|
||||||
|
snapping_type[ph::bind(&engine::api::BaseParameters::snapping, qi::_r1) = qi::_1];
|
||||||
|
|
||||||
exclude_rule = qi::lit("exclude=") >
|
exclude_rule = qi::lit("exclude=") >
|
||||||
(qi::as_string[+qi::char_("a-zA-Z0-9")] %
|
(qi::as_string[+qi::char_("a-zA-Z0-9")] %
|
||||||
',')[ph::bind(&engine::api::BaseParameters::exclude, qi::_r1) = qi::_1];
|
',')[ph::bind(&engine::api::BaseParameters::exclude, qi::_r1) = qi::_1];
|
||||||
@ -171,7 +188,9 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
| bearings_rule(qi::_r1) //
|
| bearings_rule(qi::_r1) //
|
||||||
| generate_hints_rule(qi::_r1) //
|
| generate_hints_rule(qi::_r1) //
|
||||||
| approach_rule(qi::_r1) //
|
| approach_rule(qi::_r1) //
|
||||||
| exclude_rule(qi::_r1);
|
| exclude_rule(qi::_r1) //
|
||||||
|
| snapping_rule(qi::_r1) //
|
||||||
|
| stoppage_rule(qi::_r1); //
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -188,6 +207,7 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
qi::rule<Iterator, Signature> generate_hints_rule;
|
qi::rule<Iterator, Signature> generate_hints_rule;
|
||||||
qi::rule<Iterator, Signature> approach_rule;
|
qi::rule<Iterator, Signature> approach_rule;
|
||||||
qi::rule<Iterator, Signature> exclude_rule;
|
qi::rule<Iterator, Signature> exclude_rule;
|
||||||
|
qi::rule<Iterator, Signature> stoppage_rule;
|
||||||
|
|
||||||
qi::rule<Iterator, osrm::engine::Bearing()> bearing_rule;
|
qi::rule<Iterator, osrm::engine::Bearing()> bearing_rule;
|
||||||
qi::rule<Iterator, osrm::util::Coordinate()> location_rule;
|
qi::rule<Iterator, osrm::util::Coordinate()> location_rule;
|
||||||
@ -197,11 +217,13 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
qi::rule<Iterator, unsigned char()> base64_char;
|
qi::rule<Iterator, unsigned char()> base64_char;
|
||||||
qi::rule<Iterator, std::string()> polyline_chars;
|
qi::rule<Iterator, std::string()> polyline_chars;
|
||||||
qi::rule<Iterator, double()> unlimited_rule;
|
qi::rule<Iterator, double()> unlimited_rule;
|
||||||
|
qi::rule<Iterator, Signature> snapping_rule;
|
||||||
|
|
||||||
qi::symbols<char, engine::Approach> approach_type;
|
qi::symbols<char, engine::Approach> approach_type;
|
||||||
|
qi::symbols<char, engine::api::BaseParameters::SnappingType> snapping_type;
|
||||||
};
|
};
|
||||||
}
|
} // namespace api
|
||||||
}
|
} // namespace server
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,7 +18,7 @@ namespace
|
|||||||
{
|
{
|
||||||
namespace ph = boost::phoenix;
|
namespace ph = boost::phoenix;
|
||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
template <typename Iterator = std::string::iterator,
|
template <typename Iterator = std::string::iterator,
|
||||||
typename Signature = void(engine::api::TableParameters &)>
|
typename Signature = void(engine::api::TableParameters &)>
|
||||||
@ -106,8 +106,8 @@ struct TableParametersGrammar : public BaseParametersGrammar<Iterator, Signature
|
|||||||
fallback_coordinate_type;
|
fallback_coordinate_type;
|
||||||
qi::real_parser<double, json_policy> double_;
|
qi::real_parser<double, json_policy> double_;
|
||||||
};
|
};
|
||||||
}
|
} // namespace api
|
||||||
}
|
} // namespace server
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -488,8 +488,8 @@ inline void Prettify(char *buffer, int length, int k)
|
|||||||
inline void dtoa_milo(double value, char *buffer)
|
inline void dtoa_milo(double value, char *buffer)
|
||||||
{
|
{
|
||||||
// Not handling NaN and inf
|
// Not handling NaN and inf
|
||||||
assert(!isnan(value));
|
assert(!std::isnan(value));
|
||||||
assert(!isinf(value));
|
assert(!std::isinf(value));
|
||||||
|
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ struct osm_way_id
|
|||||||
struct duplicated_node
|
struct duplicated_node
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
} // namespace tag
|
||||||
using OSMNodeID = osrm::Alias<std::uint64_t, tag::osm_node_id>;
|
using OSMNodeID = osrm::Alias<std::uint64_t, tag::osm_node_id>;
|
||||||
static_assert(std::is_pod<OSMNodeID>(), "OSMNodeID is not a valid alias");
|
static_assert(std::is_pod<OSMNodeID>(), "OSMNodeID is not a valid alias");
|
||||||
using OSMWayID = osrm::Alias<std::uint64_t, tag::osm_way_id>;
|
using OSMWayID = osrm::Alias<std::uint64_t, tag::osm_way_id>;
|
||||||
@ -116,7 +116,10 @@ static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDurati
|
|||||||
static const EdgeDistance MAXIMAL_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
static const EdgeDistance MAXIMAL_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
||||||
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
|
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
|
||||||
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
||||||
static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits<double>::max();
|
static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits<EdgeDistance>::max();
|
||||||
|
constexpr EdgeDuration INVALID_MINIMUM_STOPPAGE_PENALTY = std::numeric_limits<EdgeDuration>::max();
|
||||||
|
constexpr EdgeDuration INVALID_MAXIMUM_STOPPAGE_PENALTY = std::numeric_limits<EdgeDuration>::max();
|
||||||
|
constexpr float MAXIMAL_ACCEL_DECEL_PENALIZABLE_SPEED_INVERSE = 40.f; // seconds/metre
|
||||||
|
|
||||||
// FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent
|
// FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent
|
||||||
// within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any
|
// within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrm",
|
"name": "osrm",
|
||||||
"version": "5.21.0",
|
"version": "5.21.0-customsnapping.5",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -120,9 +120,6 @@ function setup()
|
|||||||
|
|
||||||
-- classes to support for exclude flags
|
-- classes to support for exclude flags
|
||||||
excludable = Sequence {
|
excludable = Sequence {
|
||||||
Set {'toll'},
|
|
||||||
Set {'motorway'},
|
|
||||||
Set {'ferry'}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
avoid = Set {
|
avoid = Set {
|
||||||
|
@ -86,8 +86,10 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
bool request_distance = params.annotations & api::TableParameters::AnnotationsType::Distance;
|
bool request_distance = params.annotations & api::TableParameters::AnnotationsType::Distance;
|
||||||
bool request_duration = params.annotations & api::TableParameters::AnnotationsType::Duration;
|
bool request_duration = params.annotations & api::TableParameters::AnnotationsType::Duration;
|
||||||
|
|
||||||
|
constexpr bool always_calculate_distance = true;
|
||||||
|
|
||||||
auto result_tables_pair = algorithms.ManyToManySearch(
|
auto result_tables_pair = algorithms.ManyToManySearch(
|
||||||
snapped_phantoms, params.sources, params.destinations, request_distance);
|
snapped_phantoms, params.sources, params.destinations, always_calculate_distance);
|
||||||
|
|
||||||
if ((request_duration && result_tables_pair.first.empty()) ||
|
if ((request_duration && result_tables_pair.first.empty()) ||
|
||||||
(request_distance && result_tables_pair.second.empty()))
|
(request_distance && result_tables_pair.second.empty()))
|
||||||
@ -97,8 +99,61 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
|
|
||||||
std::vector<api::TableAPI::TableCellRef> estimated_pairs;
|
std::vector<api::TableAPI::TableCellRef> estimated_pairs;
|
||||||
|
|
||||||
|
// Adds some time to adjust for getting up to speed and slowing down to a stop
|
||||||
|
// Returns a new `duration`
|
||||||
|
auto adjust_for_startstop = [](const double &comfortable_acceleration,
|
||||||
|
const EdgeDuration &duration,
|
||||||
|
const EdgeDistance &distance) -> EdgeDuration {
|
||||||
|
|
||||||
|
// Assume linear acceleration from 0 to velocity
|
||||||
|
// auto comfortable_acceleration = 1.85; // m/s^2
|
||||||
|
|
||||||
|
// Very short paths can end up with 0 duration. That'll lead to a divide
|
||||||
|
// by zero, so instead, we'll assume the travel speed is 10m/s (36km/h).
|
||||||
|
// Typically, the distance is also short, so we're quibbling at tiny numbers
|
||||||
|
// here, but tiny numbers is what this adjustment lambda is all about,
|
||||||
|
// so we do try to be reasonable.
|
||||||
|
const auto average_speed =
|
||||||
|
duration == 0 ? 10 : distance /
|
||||||
|
(duration / 10.); // duration is in deciseconds, we need m/sec
|
||||||
|
|
||||||
|
// Using the equations of motion as a simple approximation, assuming constant acceleration
|
||||||
|
// https://en.wikipedia.org/wiki/Equations_of_motion#Constant_translational_acceleration_in_a_straight_line
|
||||||
|
const auto distance_to_full_speed =
|
||||||
|
(average_speed * average_speed) / (2 * comfortable_acceleration);
|
||||||
|
|
||||||
|
/*
|
||||||
|
std::cout << "Comfortable accel is " << comfortable_acceleration << std::endl;
|
||||||
|
std::cout << "Average speed is " << average_speed << " duration is " << duration
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << "Distance is " << distance << " distance to full speed is "
|
||||||
|
<< distance_to_full_speed << std::endl;
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (distance_to_full_speed > distance / 2)
|
||||||
|
{
|
||||||
|
// std::cout << "Distance was too short, so only using half" << std::endl;
|
||||||
|
const auto time_to_halfway = std::sqrt(distance / comfortable_acceleration);
|
||||||
|
return (2 * time_to_halfway) * 10; // result is in deciseconds
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// std::cout << "Distance was long, using cruising speed" << std::endl;
|
||||||
|
const auto cruising_distance = distance - 2 * distance_to_full_speed;
|
||||||
|
const auto cruising_time = cruising_distance / average_speed;
|
||||||
|
const auto acceleration_time = average_speed / comfortable_acceleration;
|
||||||
|
|
||||||
|
// std::cout << "Cruising distance is " << cruising_distance << std::endl;
|
||||||
|
// std::cout << "Cruising time is " << cruising_time << std::endl;
|
||||||
|
// std::cout << "Acceleration time is " << acceleration_time << std::endl;
|
||||||
|
return (cruising_time + 2 * acceleration_time) * 10; // result is in deciseconds
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Scan table for null results - if any exist, replace with distance estimates
|
// Scan table for null results - if any exist, replace with distance estimates
|
||||||
if (params.fallback_speed != INVALID_FALLBACK_SPEED || params.scale_factor != 1)
|
if (params.fallback_speed != INVALID_FALLBACK_SPEED || params.scale_factor != 1 ||
|
||||||
|
(params.min_stoppage_penalty != INVALID_MINIMUM_STOPPAGE_PENALTY &&
|
||||||
|
params.max_stoppage_penalty != INVALID_MAXIMUM_STOPPAGE_PENALTY))
|
||||||
{
|
{
|
||||||
for (std::size_t row = 0; row < num_sources; row++)
|
for (std::size_t row = 0; row < num_sources; row++)
|
||||||
{
|
{
|
||||||
@ -106,6 +161,22 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
{
|
{
|
||||||
const auto &table_index = row * num_destinations + column;
|
const auto &table_index = row * num_destinations + column;
|
||||||
BOOST_ASSERT(table_index < result_tables_pair.first.size());
|
BOOST_ASSERT(table_index < result_tables_pair.first.size());
|
||||||
|
// apply an accel/deceleration penalty to the duration
|
||||||
|
if (result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION && row != column)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
const auto &source =
|
||||||
|
snapped_phantoms[params.sources.empty() ? row : params.sources[row]];
|
||||||
|
const auto &destination =
|
||||||
|
snapped_phantoms[params.destinations.empty() ? column
|
||||||
|
: params.destinations[column]];
|
||||||
|
*/
|
||||||
|
result_tables_pair.first[table_index] =
|
||||||
|
adjust_for_startstop(params.min_stoppage_penalty,
|
||||||
|
result_tables_pair.first[table_index],
|
||||||
|
result_tables_pair.second[table_index]);
|
||||||
|
}
|
||||||
|
// Estimate null results based on fallback_speed (if valid) and distance
|
||||||
if (params.fallback_speed != INVALID_FALLBACK_SPEED && params.fallback_speed > 0 &&
|
if (params.fallback_speed != INVALID_FALLBACK_SPEED && params.fallback_speed > 0 &&
|
||||||
result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION)
|
result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION)
|
||||||
{
|
{
|
||||||
@ -132,6 +203,7 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
|
|
||||||
estimated_pairs.emplace_back(row, column);
|
estimated_pairs.emplace_back(row, column);
|
||||||
}
|
}
|
||||||
|
// Apply a scale factor to non-null result if requested
|
||||||
if (params.scale_factor > 0 && params.scale_factor != 1 &&
|
if (params.scale_factor > 0 && params.scale_factor != 1 &&
|
||||||
result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION &&
|
result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION &&
|
||||||
result_tables_pair.first[table_index] != 0)
|
result_tables_pair.first[table_index] != 0)
|
||||||
@ -153,11 +225,19 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If distances weren't requested, delete them from the result so they don't
|
||||||
|
// get rendered.
|
||||||
|
if (!request_distance)
|
||||||
|
{
|
||||||
|
std::vector<EdgeDistance> empty;
|
||||||
|
result_tables_pair.second.swap(empty);
|
||||||
|
}
|
||||||
|
|
||||||
api::TableAPI table_api{facade, params};
|
api::TableAPI table_api{facade, params};
|
||||||
table_api.MakeResponse(result_tables_pair, snapped_phantoms, estimated_pairs, result);
|
table_api.MakeResponse(result_tables_pair, snapped_phantoms, estimated_pairs, result);
|
||||||
|
|
||||||
return Status::Ok;
|
return Status::Ok;
|
||||||
}
|
}
|
||||||
}
|
} // namespace plugins
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
@ -606,3 +606,23 @@ test('route: route in Monaco without motorways', function(assert) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('route: throws on invalid snapping values', function (assert) {
|
||||||
|
assert.plan(1);
|
||||||
|
var osrm = new OSRM(monaco_path);
|
||||||
|
var options = {
|
||||||
|
steps: true,
|
||||||
|
coordinates: three_test_coordinates.concat(three_test_coordinates),
|
||||||
|
snapping: "zing"
|
||||||
|
};
|
||||||
|
assert.throws(function () { osrm.route(options, function (err, response) { console.error(`response: ${response}`); console.error(`error: ${err}`); }); },
|
||||||
|
/'snapping' param must be one of \[default, any\]/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('route: snapping parameter passed through OK', function(assert) {
|
||||||
|
assert.plan(2);
|
||||||
|
var osrm = new OSRM(monaco_path);
|
||||||
|
osrm.route({snapping: "any", coordinates: [[7.448205209414596,43.754001097311544],[7.447122039202185,43.75306156811368]]}, function(err, route) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(Math.round(route.routes[0].distance * 10), 1314); // Round it to nearest 0.1m to eliminate floating point comparison error
|
||||||
|
});
|
||||||
|
});
|
@ -48,6 +48,21 @@ test('table: test annotations paramater combination', function(assert) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('table: snapping parameter passed through OK', function(assert) {
|
||||||
|
assert.plan(2);
|
||||||
|
var osrm = new OSRM(data_path);
|
||||||
|
var options = {
|
||||||
|
coordinates: [[7.448205209414596,43.754001097311544],[7.447122039202185,43.75306156811368]],
|
||||||
|
annotations: ['duration', 'distance'],
|
||||||
|
snapping: 'any'
|
||||||
|
};
|
||||||
|
console.log(options);
|
||||||
|
osrm.table(options, function(err, result) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(Math.round(result.distances[0][1] * 10), 1315); // Round it to nearest 0.1m to eliminate floating point comparison error
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('table: returns buffer', function(assert) {
|
test('table: returns buffer', function(assert) {
|
||||||
assert.plan(3);
|
assert.plan(3);
|
||||||
var osrm = new OSRM(data_path);
|
var osrm = new OSRM(data_path);
|
||||||
@ -303,5 +318,33 @@ tables.forEach(function(annotation) {
|
|||||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /scale_factor must be > 0/, "should throw on invalid scale_factor value");
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /scale_factor must be > 0/, "should throw on invalid scale_factor value");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('table: ' + annotation + ' table in Monaco with stoppage_penalty values', function(assert) {
|
||||||
|
assert.plan(6);
|
||||||
|
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
||||||
|
var options = {
|
||||||
|
coordinates: two_test_coordinates,
|
||||||
|
annotations: [annotation.slice(0,-1)],
|
||||||
|
stoppage_penalty: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /Stoppage penalty must be an array of 2 numbers/, "should throw on empty array");
|
||||||
|
|
||||||
|
options.stoppage_penalty = ['a',1];
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /Stoppage penalty must be an array of 2 numbers/, "should throw on non-numeric value");
|
||||||
|
|
||||||
|
options.stoppage_penalty = [1,2,3];
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /Stoppage penalty must be an array of 2 numbers/, "should throw on too many values");
|
||||||
|
|
||||||
|
options.stoppage_penalty = [1];
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /Stoppage penalty must be an array of 2 numbers/, "should throw on not enough values");
|
||||||
|
|
||||||
|
options.stoppage_penalty = [2,1];
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /Stoppage penalty max must be larger than min/, "should throw on max < min");
|
||||||
|
|
||||||
|
options.stoppage_penalty = [-1,2];
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /Stoppage penalty min\/max can't be less than zero/, "should throw on negative value");
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -282,36 +282,48 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
const util::Coordinate /*input_coordinate*/,
|
||||||
const Approach /*approach*/) const override
|
const Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */,
|
||||||
|
const double /* min_stoppage_penalty */,
|
||||||
|
const double /* max_stoppage_penalty */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
const util::Coordinate /*input_coordinate*/,
|
||||||
const double /*max_distance*/,
|
const double /*max_distance*/,
|
||||||
const Approach /*approach*/) const override
|
const Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */,
|
||||||
|
const double /* min_stoppage_penalty */,
|
||||||
|
const double /* max_stoppage_penalty */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
const util::Coordinate /*input_coordinate*/,
|
||||||
const double /*max_distance*/,
|
const double /*max_distance*/,
|
||||||
const int /*bearing*/,
|
const int /*bearing*/,
|
||||||
const int /*bearing_range*/,
|
const int /*bearing_range*/,
|
||||||
const Approach /*approach*/) const override
|
const Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */,
|
||||||
|
const double /* min_stoppage_penalty */,
|
||||||
|
const double /* max_stoppage_penalty */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
const util::Coordinate /*input_coordinate*/,
|
||||||
const int /*bearing*/,
|
const int /*bearing*/,
|
||||||
const int /*bearing_range*/,
|
const int /*bearing_range*/,
|
||||||
const Approach /*approach*/) const override
|
const Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */,
|
||||||
|
const double /* min_stoppage_penalty */,
|
||||||
|
const double /* max_stoppage_penalty */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,10 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
|||||||
std::pair<engine::PhantomNode, engine::PhantomNode>
|
std::pair<engine::PhantomNode, engine::PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
const util::Coordinate /*input_coordinate*/,
|
const util::Coordinate /*input_coordinate*/,
|
||||||
const engine::Approach /*approach*/) const override
|
const engine::Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */,
|
||||||
|
const double /* min_stoppage_penalty */,
|
||||||
|
const double /* max_stoppage_penalty */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -178,7 +181,10 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
|||||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
const util::Coordinate /*input_coordinate*/,
|
const util::Coordinate /*input_coordinate*/,
|
||||||
const double /*max_distance*/,
|
const double /*max_distance*/,
|
||||||
const engine::Approach /*approach*/) const override
|
const engine::Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */,
|
||||||
|
const double /* min_stoppage_penalty */,
|
||||||
|
const double /* max_stoppage_penalty */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -189,7 +195,10 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
|||||||
const double /*max_distance*/,
|
const double /*max_distance*/,
|
||||||
const int /*bearing*/,
|
const int /*bearing*/,
|
||||||
const int /*bearing_range*/,
|
const int /*bearing_range*/,
|
||||||
const engine::Approach /*approach*/) const override
|
const engine::Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */,
|
||||||
|
const double /* min_stoppage_penalty */,
|
||||||
|
const double /* max_stoppage_penalty */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -199,7 +208,10 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
|||||||
const util::Coordinate /*input_coordinate*/,
|
const util::Coordinate /*input_coordinate*/,
|
||||||
const int /*bearing*/,
|
const int /*bearing*/,
|
||||||
const int /*bearing_range*/,
|
const int /*bearing_range*/,
|
||||||
const engine::Approach /*approach*/) const override
|
const engine::Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */,
|
||||||
|
const double /* min_stoppage_penalty */,
|
||||||
|
const double /* max_stoppage_penalty */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user