Optimise R-tree queries in the case if there is no need to limit maximum number of results
This commit is contained in:
parent
54e50a67a8
commit
1d17ff2fb5
@ -375,7 +375,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodes(
|
return m_geospatial_query->NearestPhantomNodes(
|
||||||
input_coordinate, approach, boost::none, max_distance, bearing, use_all_edges);
|
input_coordinate, approach, max_distance, bearing, use_all_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PhantomNodeWithDistance>
|
std::vector<PhantomNodeWithDistance>
|
||||||
|
@ -47,6 +47,50 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
return rtree.SearchInBox(bbox);
|
return rtree.SearchInBox(bbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<PhantomNodeWithDistance>
|
||||||
|
NearestPhantomNodes(const util::Coordinate input_coordinate,
|
||||||
|
const Approach approach,
|
||||||
|
const double max_distance,
|
||||||
|
const boost::optional<Bearing> bearing_with_range,
|
||||||
|
const boost::optional<bool> use_all_edges) const
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
return NearestPhantomNodes(input_coordinate,
|
||||||
|
approach,
|
||||||
|
boost::optional<size_t>{},
|
||||||
|
max_distance,
|
||||||
|
bearing_with_range,
|
||||||
|
use_all_edges);
|
||||||
|
#else
|
||||||
|
auto results = rtree.SearchInRange(
|
||||||
|
input_coordinate,
|
||||||
|
max_distance,
|
||||||
|
[this, approach, &input_coordinate, &bearing_with_range, &use_all_edges, max_distance](
|
||||||
|
const CandidateSegment &segment)
|
||||||
|
{
|
||||||
|
auto invalidDistance =
|
||||||
|
CheckSegmentDistance(input_coordinate, segment, max_distance);
|
||||||
|
if (invalidDistance)
|
||||||
|
{
|
||||||
|
return std::pair<bool, bool>{false, false};
|
||||||
|
}
|
||||||
|
(void)approach;
|
||||||
|
(void)use_all_edges;
|
||||||
|
(void)bearing_with_range;
|
||||||
|
(void)use_all_edges;
|
||||||
|
|
||||||
|
auto valid = CheckSegmentExclude(segment) &&
|
||||||
|
CheckApproach(input_coordinate, segment, approach) &&
|
||||||
|
(use_all_edges ? HasValidEdge(segment, *use_all_edges)
|
||||||
|
: HasValidEdge(segment)) &&
|
||||||
|
(bearing_with_range ? CheckSegmentBearing(segment, *bearing_with_range)
|
||||||
|
: std::make_pair(true, true));
|
||||||
|
return valid;
|
||||||
|
});
|
||||||
|
return MakePhantomNodes(input_coordinate, results);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Returns max_results nearest PhantomNodes that are valid within the provided parameters.
|
// Returns max_results nearest PhantomNodes that are valid within the provided parameters.
|
||||||
// Does not filter by small/big component!
|
// Does not filter by small/big component!
|
||||||
std::vector<PhantomNodeWithDistance>
|
std::vector<PhantomNodeWithDistance>
|
||||||
@ -294,6 +338,11 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
distance_and_phantoms.begin(),
|
distance_and_phantoms.begin(),
|
||||||
[this, &input_coordinate](const CandidateSegment &segment)
|
[this, &input_coordinate](const CandidateSegment &segment)
|
||||||
{ return MakePhantomNode(input_coordinate, segment.data); });
|
{ return MakePhantomNode(input_coordinate, segment.data); });
|
||||||
|
std::sort(distance_and_phantoms.begin(), distance_and_phantoms.end(), [](const auto &lhs,
|
||||||
|
const auto &rhs)
|
||||||
|
{
|
||||||
|
return lhs.distance < rhs.distance;
|
||||||
|
});
|
||||||
return distance_and_phantoms;
|
return distance_and_phantoms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef OSRM_UTIL_RECTANGLE_HPP
|
#ifndef OSRM_UTIL_RECTANGLE_HPP
|
||||||
#define OSRM_UTIL_RECTANGLE_HPP
|
#define OSRM_UTIL_RECTANGLE_HPP
|
||||||
|
|
||||||
|
#include "coordinate.hpp"
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
|
|
||||||
@ -168,6 +169,26 @@ struct RectangleInt2D
|
|||||||
min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::max()} &&
|
min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::max()} &&
|
||||||
max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()};
|
max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double MetersPerLngDegree(const FixedLatitude lat)
|
||||||
|
{
|
||||||
|
constexpr static double kMetersPerDegreeLat = 110567.0f;
|
||||||
|
|
||||||
|
constexpr float kRadPerDeg = (3.14 /* TODO */ / 180.0f);
|
||||||
|
|
||||||
|
return std::cos(kRadPerDeg * static_cast<double>(toFloating(lat))) * kMetersPerDegreeLat;
|
||||||
|
}
|
||||||
|
static RectangleInt2D ExpandMeters(const Coordinate &coordinate, const double meters)
|
||||||
|
{
|
||||||
|
constexpr static double kMetersPerDegreeLat = 110567.0f;
|
||||||
|
const double lat_offset = meters / kMetersPerDegreeLat;
|
||||||
|
const double lon_offset = meters / MetersPerLngDegree(coordinate.lat);
|
||||||
|
|
||||||
|
return RectangleInt2D{coordinate.lon - toFixed(FloatLongitude{lon_offset}),
|
||||||
|
coordinate.lon + toFixed(FloatLongitude{lon_offset}),
|
||||||
|
coordinate.lat - toFixed(FloatLatitude{lat_offset}),
|
||||||
|
coordinate.lat + toFixed(FloatLatitude{lat_offset})};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace osrm::util
|
} // namespace osrm::util
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#define STATIC_RTREE_HPP
|
#define STATIC_RTREE_HPP
|
||||||
|
|
||||||
#include "storage/tar_fwd.hpp"
|
#include "storage/tar_fwd.hpp"
|
||||||
|
|
||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/deallocating_vector.hpp"
|
#include "util/deallocating_vector.hpp"
|
||||||
@ -11,6 +10,7 @@
|
|||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
#include "util/mmap_file.hpp"
|
#include "util/mmap_file.hpp"
|
||||||
#include "util/rectangle.hpp"
|
#include "util/rectangle.hpp"
|
||||||
|
#include "util/timing_util.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
#include "util/vector_view.hpp"
|
#include "util/vector_view.hpp"
|
||||||
#include "util/web_mercator.hpp"
|
#include "util/web_mercator.hpp"
|
||||||
@ -565,6 +565,57 @@ class StaticRTree
|
|||||||
{ return num_results >= max_results; });
|
{ return num_results >= max_results; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double GetSegmentDistance(const Coordinate input_coordinate,
|
||||||
|
const CandidateSegment &segment) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(segment.data.forward_segment_id.id != SPECIAL_SEGMENTID ||
|
||||||
|
!segment.data.forward_segment_id.enabled);
|
||||||
|
BOOST_ASSERT(segment.data.reverse_segment_id.id != SPECIAL_SEGMENTID ||
|
||||||
|
!segment.data.reverse_segment_id.enabled);
|
||||||
|
|
||||||
|
Coordinate wsg84_coordinate =
|
||||||
|
util::web_mercator::toWGS84(segment.fixed_projected_coordinate);
|
||||||
|
|
||||||
|
return util::coordinate_calculation::greatCircleDistance(input_coordinate,
|
||||||
|
wsg84_coordinate);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FilterT>
|
||||||
|
std::vector<CandidateSegment> SearchInRange(const Coordinate input_coordinate,
|
||||||
|
double maxDistanceMeters,
|
||||||
|
const FilterT filter) const
|
||||||
|
{
|
||||||
|
(void)filter;
|
||||||
|
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
|
||||||
|
Coordinate fixed_projected_coordinate{projected_coordinate};
|
||||||
|
|
||||||
|
auto bbox = Rectangle::ExpandMeters(input_coordinate, maxDistanceMeters);
|
||||||
|
auto results_in_bbox = SearchInBox(bbox);
|
||||||
|
std::vector<CandidateSegment> results;
|
||||||
|
for (const auto ¤t_edge : results_in_bbox)
|
||||||
|
{
|
||||||
|
const auto projected_u = web_mercator::fromWGS84(m_coordinate_list[current_edge.u]);
|
||||||
|
const auto projected_v = web_mercator::fromWGS84(m_coordinate_list[current_edge.v]);
|
||||||
|
|
||||||
|
FloatCoordinate projected_nearest;
|
||||||
|
std::tie(std::ignore, projected_nearest) =
|
||||||
|
coordinate_calculation::projectPointOnSegment(
|
||||||
|
projected_u, projected_v, fixed_projected_coordinate);
|
||||||
|
|
||||||
|
CandidateSegment current_candidate{projected_nearest, current_edge};
|
||||||
|
auto use_segment = filter(current_candidate);
|
||||||
|
if (!use_segment.first && !use_segment.second)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
current_candidate.data.forward_segment_id.enabled &= use_segment.first;
|
||||||
|
current_candidate.data.reverse_segment_id.enabled &= use_segment.second;
|
||||||
|
|
||||||
|
results.push_back(std::move(current_candidate));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
// Return edges in distance order with the coordinate of the closest point on the edge.
|
// Return edges in distance order with the coordinate of the closest point on the edge.
|
||||||
template <typename FilterT, typename TerminationT>
|
template <typename FilterT, typename TerminationT>
|
||||||
std::vector<CandidateSegment> Nearest(const Coordinate input_coordinate,
|
std::vector<CandidateSegment> Nearest(const Coordinate input_coordinate,
|
||||||
@ -572,8 +623,10 @@ class StaticRTree
|
|||||||
const TerminationT terminate) const
|
const TerminationT terminate) const
|
||||||
{
|
{
|
||||||
std::vector<CandidateSegment> results;
|
std::vector<CandidateSegment> results;
|
||||||
|
|
||||||
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
|
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
|
||||||
Coordinate fixed_projected_coordinate{projected_coordinate};
|
Coordinate fixed_projected_coordinate{projected_coordinate};
|
||||||
|
|
||||||
// initialize queue with root element
|
// initialize queue with root element
|
||||||
std::priority_queue<QueryCandidate> traversal_queue;
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
traversal_queue.push(QueryCandidate{0, TreeIndex{}});
|
traversal_queue.push(QueryCandidate{0, TreeIndex{}});
|
||||||
|
@ -224,6 +224,7 @@ try
|
|||||||
if (rc != Status::Ok ||
|
if (rc != Status::Ok ||
|
||||||
json_result.values.at("matchings").get<json::Array>().values.size() != 1)
|
json_result.values.at("matchings").get<json::Array>().values.size() != 1)
|
||||||
{
|
{
|
||||||
|
std::cerr << "Failure\n";
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user