Refactor StaticRTree to remove application dependent code
StaticRTree now acts like a container, just returning the input data (NodeBasedEdge) and not PhantomNodes.
This commit is contained in:
@@ -26,6 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../../algorithms/coordinate_calculation.hpp"
|
||||
#include "../../algorithms/geospatial_query.hpp"
|
||||
#include "../../data_structures/static_rtree.hpp"
|
||||
#include "../../data_structures/query_node.hpp"
|
||||
#include "../../data_structures/edge_based_node.hpp"
|
||||
@@ -55,11 +56,12 @@ constexpr uint32_t TEST_BRANCHING_FACTOR = 8;
|
||||
constexpr uint32_t TEST_LEAF_NODE_SIZE = 64;
|
||||
|
||||
typedef EdgeBasedNode TestData;
|
||||
typedef StaticRTree<TestData,
|
||||
std::vector<FixedPointCoordinate>,
|
||||
false,
|
||||
TEST_BRANCHING_FACTOR,
|
||||
TEST_LEAF_NODE_SIZE> TestStaticRTree;
|
||||
using TestStaticRTree = StaticRTree<TestData,
|
||||
std::vector<FixedPointCoordinate>,
|
||||
false,
|
||||
TEST_BRANCHING_FACTOR,
|
||||
TEST_LEAF_NODE_SIZE>;
|
||||
using MiniStaticRTree = StaticRTree<TestData, std::vector<FixedPointCoordinate>, false, 2, 3>;
|
||||
|
||||
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
|
||||
constexpr unsigned RANDOM_SEED = 42;
|
||||
@@ -68,113 +70,35 @@ static const int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
|
||||
static const int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
|
||||
static const int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
|
||||
|
||||
class LinearSearchNN
|
||||
template <typename DataT> class LinearSearchNN
|
||||
{
|
||||
public:
|
||||
LinearSearchNN(const std::shared_ptr<std::vector<FixedPointCoordinate>> &coords,
|
||||
const std::vector<TestData> &edges)
|
||||
const std::vector<DataT> &edges)
|
||||
: coords(coords), edges(edges)
|
||||
{
|
||||
}
|
||||
|
||||
bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
|
||||
FixedPointCoordinate &result_coordinate)
|
||||
std::vector<DataT> Nearest(const FixedPointCoordinate &input_coordinate,
|
||||
const unsigned num_results)
|
||||
{
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
FixedPointCoordinate min_coord;
|
||||
for (const TestData &e : edges)
|
||||
{
|
||||
const FixedPointCoordinate &start = coords->at(e.u);
|
||||
const FixedPointCoordinate &end = coords->at(e.v);
|
||||
float distance = coordinate_calculation::great_circle_distance(
|
||||
input_coordinate.lat, input_coordinate.lon, start.lat, start.lon);
|
||||
if (distance < min_dist)
|
||||
std::vector<DataT> local_edges(edges);
|
||||
|
||||
std::nth_element(
|
||||
local_edges.begin(), local_edges.begin() + num_results, local_edges.end(),
|
||||
[this, &input_coordinate](const DataT &lhs, const DataT &rhs)
|
||||
{
|
||||
min_coord = start;
|
||||
min_dist = distance;
|
||||
}
|
||||
float current_ratio = 0.;
|
||||
FixedPointCoordinate nearest;
|
||||
const float lhs_dist = coordinate_calculation::perpendicular_distance(
|
||||
coords->at(lhs.u), coords->at(lhs.v), input_coordinate, nearest, current_ratio);
|
||||
const float rhs_dist = coordinate_calculation::perpendicular_distance(
|
||||
coords->at(rhs.u), coords->at(rhs.v), input_coordinate, nearest, current_ratio);
|
||||
return lhs_dist < rhs_dist;
|
||||
});
|
||||
local_edges.resize(num_results);
|
||||
|
||||
distance = coordinate_calculation::great_circle_distance(
|
||||
input_coordinate.lat, input_coordinate.lon, end.lat, end.lon);
|
||||
if (distance < min_dist)
|
||||
{
|
||||
min_coord = end;
|
||||
min_dist = distance;
|
||||
}
|
||||
}
|
||||
|
||||
result_coordinate = min_coord;
|
||||
return result_coordinate.is_valid();
|
||||
}
|
||||
|
||||
bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
|
||||
PhantomNode &result_phantom_node,
|
||||
const unsigned)
|
||||
{
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
TestData nearest_edge;
|
||||
for (const TestData &e : edges)
|
||||
{
|
||||
if (e.component.is_tiny)
|
||||
continue;
|
||||
|
||||
float current_ratio = 0.;
|
||||
FixedPointCoordinate nearest;
|
||||
const float current_perpendicular_distance =
|
||||
coordinate_calculation::perpendicular_distance(
|
||||
coords->at(e.u), coords->at(e.v), input_coordinate, nearest, current_ratio);
|
||||
|
||||
if ((current_perpendicular_distance < min_dist) &&
|
||||
!osrm::epsilon_compare(current_perpendicular_distance, min_dist))
|
||||
{ // found a new minimum
|
||||
min_dist = current_perpendicular_distance;
|
||||
result_phantom_node = {e.forward_edge_based_node_id,
|
||||
e.reverse_edge_based_node_id,
|
||||
e.name_id,
|
||||
e.forward_weight,
|
||||
e.reverse_weight,
|
||||
e.forward_offset,
|
||||
e.reverse_offset,
|
||||
e.packed_geometry_id,
|
||||
e.component.is_tiny,
|
||||
e.component.id,
|
||||
nearest,
|
||||
e.fwd_segment_position,
|
||||
e.forward_travel_mode,
|
||||
e.backward_travel_mode};
|
||||
nearest_edge = e;
|
||||
}
|
||||
}
|
||||
|
||||
if (result_phantom_node.location.is_valid())
|
||||
{
|
||||
// Hack to fix rounding errors and wandering via nodes.
|
||||
if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon))
|
||||
{
|
||||
result_phantom_node.location.lon = input_coordinate.lon;
|
||||
}
|
||||
if (1 == std::abs(input_coordinate.lat - result_phantom_node.location.lat))
|
||||
{
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
}
|
||||
|
||||
const float distance_1 = coordinate_calculation::great_circle_distance(
|
||||
coords->at(nearest_edge.u), result_phantom_node.location);
|
||||
const float distance_2 = coordinate_calculation::great_circle_distance(
|
||||
coords->at(nearest_edge.u), coords->at(nearest_edge.v));
|
||||
const float ratio = std::min(1.f, distance_1 / distance_2);
|
||||
|
||||
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
|
||||
{
|
||||
result_phantom_node.forward_weight *= ratio;
|
||||
}
|
||||
if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
|
||||
{
|
||||
result_phantom_node.reverse_weight *= (1. - ratio);
|
||||
}
|
||||
}
|
||||
|
||||
return result_phantom_node.location.is_valid();
|
||||
return local_edges;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -295,23 +219,18 @@ void simple_verify_rtree(RTreeT &rtree,
|
||||
BOOST_TEST_MESSAGE("Verify end points");
|
||||
for (const auto &e : edges)
|
||||
{
|
||||
FixedPointCoordinate result_u, result_v;
|
||||
const FixedPointCoordinate &pu = coords->at(e.u);
|
||||
const FixedPointCoordinate &pv = coords->at(e.v);
|
||||
bool found_u = rtree.LocateClosestEndPointForCoordinate(pu, result_u, 1);
|
||||
bool found_v = rtree.LocateClosestEndPointForCoordinate(pv, result_v, 1);
|
||||
BOOST_CHECK(found_u && found_v);
|
||||
float dist_u =
|
||||
coordinate_calculation::great_circle_distance(result_u.lat, result_u.lon, pu.lat, pu.lon);
|
||||
BOOST_CHECK_LE(dist_u, std::numeric_limits<float>::epsilon());
|
||||
float dist_v =
|
||||
coordinate_calculation::great_circle_distance(result_v.lat, result_v.lon, pv.lat, pv.lon);
|
||||
BOOST_CHECK_LE(dist_v, std::numeric_limits<float>::epsilon());
|
||||
auto result_u = rtree.Nearest(pu, 1);
|
||||
auto result_v = rtree.Nearest(pv, 1);
|
||||
BOOST_CHECK(result_u.size() == 1 && result_v.size() == 1);
|
||||
BOOST_CHECK(result_u.front().u == e.u || result_u.front().v == e.u);
|
||||
BOOST_CHECK(result_v.front().u == e.v || result_v.front().v == e.v);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RTreeT>
|
||||
void sampling_verify_rtree(RTreeT &rtree, LinearSearchNN &lsnn, unsigned num_samples)
|
||||
void sampling_verify_rtree(RTreeT &rtree, LinearSearchNN<TestData> &lsnn, const std::vector<FixedPointCoordinate>& coords, unsigned num_samples)
|
||||
{
|
||||
std::mt19937 g(RANDOM_SEED);
|
||||
std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
|
||||
@@ -325,17 +244,22 @@ void sampling_verify_rtree(RTreeT &rtree, LinearSearchNN &lsnn, unsigned num_sam
|
||||
BOOST_TEST_MESSAGE("Sampling queries");
|
||||
for (const auto &q : queries)
|
||||
{
|
||||
FixedPointCoordinate result_rtree;
|
||||
rtree.LocateClosestEndPointForCoordinate(q, result_rtree, 1);
|
||||
FixedPointCoordinate result_ln;
|
||||
lsnn.LocateClosestEndPointForCoordinate(q, result_ln);
|
||||
BOOST_CHECK_EQUAL(result_ln, result_rtree);
|
||||
auto result_rtree = rtree.Nearest(q, 1);
|
||||
auto result_lsnn = lsnn.Nearest(q, 1);
|
||||
BOOST_CHECK(result_rtree.size() == 1);
|
||||
BOOST_CHECK(result_lsnn.size() == 1);
|
||||
auto rtree_u = result_rtree.back().u;
|
||||
auto rtree_v = result_rtree.back().v;
|
||||
auto lsnn_u = result_lsnn.back().u;
|
||||
auto lsnn_v = result_lsnn.back().v;
|
||||
|
||||
PhantomNode phantom_rtree;
|
||||
rtree.FindPhantomNodeForCoordinate(q, phantom_rtree, 1);
|
||||
PhantomNode phantom_ln;
|
||||
lsnn.FindPhantomNodeForCoordinate(q, phantom_ln, 1);
|
||||
BOOST_CHECK_EQUAL(phantom_rtree, phantom_ln);
|
||||
float current_ratio = 0.;
|
||||
FixedPointCoordinate nearest;
|
||||
const float rtree_dist = coordinate_calculation::perpendicular_distance(
|
||||
coords[rtree_u], coords[rtree_v], q, nearest, current_ratio);
|
||||
const float lsnn_dist = coordinate_calculation::perpendicular_distance(
|
||||
coords[lsnn_u], coords[lsnn_v], q, nearest, current_ratio);
|
||||
BOOST_CHECK_LE(std::abs(rtree_dist - lsnn_dist), std::numeric_limits<float>::epsilon());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,10 +289,10 @@ void construction_test(const std::string &prefix, FixtureT *fixture)
|
||||
std::string nodes_path;
|
||||
build_rtree<FixtureT, RTreeT>(prefix, fixture, leaves_path, nodes_path);
|
||||
RTreeT rtree(nodes_path, leaves_path, fixture->coords);
|
||||
LinearSearchNN lsnn(fixture->coords, fixture->edges);
|
||||
LinearSearchNN<TestData> lsnn(fixture->coords, fixture->edges);
|
||||
|
||||
simple_verify_rtree(rtree, fixture->coords, fixture->edges);
|
||||
sampling_verify_rtree(rtree, lsnn, 100);
|
||||
sampling_verify_rtree(rtree, lsnn, *fixture->coords, 100);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(construct_half_leaf_test, TestRandomGraphFixture_LeafHalfFull)
|
||||
@@ -396,51 +320,43 @@ BOOST_FIXTURE_TEST_CASE(construct_multiple_levels_test, TestRandomGraphFixture_M
|
||||
construction_test("test_5", this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bug: If you querry a point that lies between two BBs that have a gap,
|
||||
* one BB will be pruned, even if it could contain a nearer match.
|
||||
*/
|
||||
// Bug: If you querry a point that lies between two BBs that have a gap,
|
||||
// one BB will be pruned, even if it could contain a nearer match.
|
||||
BOOST_AUTO_TEST_CASE(regression_test)
|
||||
{
|
||||
typedef std::pair<float, float> Coord;
|
||||
typedef std::pair<unsigned, unsigned> Edge;
|
||||
using Coord = std::pair<float, float>;
|
||||
using Edge = std::pair<unsigned, unsigned>;
|
||||
GraphFixture fixture(
|
||||
{
|
||||
Coord(40.0, 0.0),
|
||||
Coord(35.0, 5.0),
|
||||
Coord(40.0, 0.0), Coord(35.0, 5.0),
|
||||
|
||||
Coord(5.0, 5.0),
|
||||
Coord(0.0, 10.0),
|
||||
Coord(5.0, 5.0), Coord(0.0, 10.0),
|
||||
|
||||
Coord(20.0, 10.0),
|
||||
Coord(20.0, 5.0),
|
||||
Coord(20.0, 10.0), Coord(20.0, 5.0),
|
||||
|
||||
Coord(40.0, 100.0),
|
||||
Coord(35.0, 105.0),
|
||||
Coord(40.0, 100.0), Coord(35.0, 105.0),
|
||||
|
||||
Coord(5.0, 105.0),
|
||||
Coord(0.0, 110.0),
|
||||
Coord(5.0, 105.0), Coord(0.0, 110.0),
|
||||
},
|
||||
{Edge(0, 1), Edge(2, 3), Edge(4, 5), Edge(6, 7), Edge(8, 9)});
|
||||
|
||||
typedef StaticRTree<TestData, std::vector<FixedPointCoordinate>, false, 2, 3> MiniStaticRTree;
|
||||
|
||||
std::string leaves_path;
|
||||
std::string nodes_path;
|
||||
build_rtree<GraphFixture, MiniStaticRTree>("test_regression", &fixture, leaves_path,
|
||||
nodes_path);
|
||||
MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords);
|
||||
LinearSearchNN<TestData> lsnn(fixture.coords, fixture.edges);
|
||||
|
||||
// query a node just right of the center of the gap
|
||||
FixedPointCoordinate input(20.0 * COORDINATE_PRECISION, 55.1 * COORDINATE_PRECISION);
|
||||
FixedPointCoordinate result;
|
||||
rtree.LocateClosestEndPointForCoordinate(input, result, 1);
|
||||
FixedPointCoordinate result_ln;
|
||||
LinearSearchNN lsnn(fixture.coords, fixture.edges);
|
||||
lsnn.LocateClosestEndPointForCoordinate(input, result_ln);
|
||||
auto result_rtree = rtree.Nearest(input, 1);
|
||||
auto result_ls = lsnn.Nearest(input, 1);
|
||||
|
||||
// TODO: reactivate
|
||||
// BOOST_CHECK_EQUAL(result_ln, result);
|
||||
BOOST_CHECK(result_rtree.size() == 1);
|
||||
BOOST_CHECK(result_ls.size() == 1);
|
||||
|
||||
BOOST_CHECK_EQUAL(result_ls.front().u, result_rtree.front().u);
|
||||
BOOST_CHECK_EQUAL(result_ls.front().v, result_rtree.front().v);
|
||||
}
|
||||
|
||||
void TestRectangle(double width, double height, double center_lat, double center_lon)
|
||||
@@ -448,7 +364,7 @@ void TestRectangle(double width, double height, double center_lat, double center
|
||||
FixedPointCoordinate center(center_lat * COORDINATE_PRECISION,
|
||||
center_lon * COORDINATE_PRECISION);
|
||||
|
||||
TestStaticRTree::RectangleT rect;
|
||||
TestStaticRTree::Rectangle rect;
|
||||
rect.min_lat = center.lat - height / 2.0 * COORDINATE_PRECISION;
|
||||
rect.max_lat = center.lat + height / 2.0 * COORDINATE_PRECISION;
|
||||
rect.min_lon = center.lon - width / 2.0 * COORDINATE_PRECISION;
|
||||
@@ -502,100 +418,63 @@ BOOST_AUTO_TEST_CASE(rectangle_test)
|
||||
TestRectangle(10, 10, 0, 0);
|
||||
}
|
||||
|
||||
/* Verify that the bearing-bounds checking function behaves as expected */
|
||||
BOOST_AUTO_TEST_CASE(bearing_range_test)
|
||||
{
|
||||
// Simple, non-edge-case checks
|
||||
BOOST_CHECK_EQUAL(true, TestStaticRTree::IsBearingWithinBounds(45, 45, 10));
|
||||
BOOST_CHECK_EQUAL(true, TestStaticRTree::IsBearingWithinBounds(35, 45, 10));
|
||||
BOOST_CHECK_EQUAL(true, TestStaticRTree::IsBearingWithinBounds(55, 45, 10));
|
||||
|
||||
BOOST_CHECK_EQUAL(false, TestStaticRTree::IsBearingWithinBounds(34, 45, 10));
|
||||
BOOST_CHECK_EQUAL(false, TestStaticRTree::IsBearingWithinBounds(56, 45, 10));
|
||||
|
||||
BOOST_CHECK_EQUAL(false, TestStaticRTree::IsBearingWithinBounds(34, 45, 10));
|
||||
BOOST_CHECK_EQUAL(false, TestStaticRTree::IsBearingWithinBounds(56, 45, 10));
|
||||
|
||||
// When angle+limit goes > 360
|
||||
BOOST_CHECK_EQUAL(true, TestStaticRTree::IsBearingWithinBounds(359, 355, 10));
|
||||
|
||||
// When angle-limit goes < 0
|
||||
BOOST_CHECK_EQUAL(true, TestStaticRTree::IsBearingWithinBounds(359, 5, 10));
|
||||
BOOST_CHECK_EQUAL(false, TestStaticRTree::IsBearingWithinBounds(354, 5, 10));
|
||||
BOOST_CHECK_EQUAL(false, TestStaticRTree::IsBearingWithinBounds(16, 5, 10));
|
||||
|
||||
|
||||
// Checking other cases of wraparound
|
||||
BOOST_CHECK_EQUAL(true, TestStaticRTree::IsBearingWithinBounds(359, -5, 10));
|
||||
BOOST_CHECK_EQUAL(false, TestStaticRTree::IsBearingWithinBounds(344, -5, 10));
|
||||
BOOST_CHECK_EQUAL(false, TestStaticRTree::IsBearingWithinBounds(6, -5, 10));
|
||||
|
||||
BOOST_CHECK_EQUAL(true, TestStaticRTree::IsBearingWithinBounds(-1, 5, 10));
|
||||
BOOST_CHECK_EQUAL(false, TestStaticRTree::IsBearingWithinBounds(-6, 5, 10));
|
||||
|
||||
BOOST_CHECK_EQUAL(true, TestStaticRTree::IsBearingWithinBounds(-721, 5, 10));
|
||||
BOOST_CHECK_EQUAL(true, TestStaticRTree::IsBearingWithinBounds(719, 5, 10));
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bearing_tests)
|
||||
{
|
||||
|
||||
typedef std::pair<float, float> Coord;
|
||||
typedef std::pair<unsigned, unsigned> Edge;
|
||||
using Coord = std::pair<float, float>;
|
||||
using Edge = std::pair<unsigned, unsigned>;
|
||||
GraphFixture fixture(
|
||||
{
|
||||
Coord(0.0, 0.0),
|
||||
Coord(10.0, 10.0),
|
||||
Coord(0.0, 0.0), Coord(10.0, 10.0),
|
||||
},
|
||||
{Edge(0, 1), Edge(1,0)});
|
||||
|
||||
typedef StaticRTree<TestData, std::vector<FixedPointCoordinate>, false, 2, 3> MiniStaticRTree;
|
||||
{Edge(0, 1), Edge(1, 0)});
|
||||
|
||||
std::string leaves_path;
|
||||
std::string nodes_path;
|
||||
build_rtree<GraphFixture, MiniStaticRTree>("test_bearing", &fixture, leaves_path, nodes_path);
|
||||
MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords);
|
||||
GeospatialQuery<MiniStaticRTree> query(rtree, fixture.coords);
|
||||
|
||||
FixedPointCoordinate input(5.0 * COORDINATE_PRECISION, 5.1 * COORDINATE_PRECISION);
|
||||
std::vector<PhantomNode> results;
|
||||
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate( input, results, 5);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
BOOST_CHECK_EQUAL(results.back().forward_node_id, 0);
|
||||
BOOST_CHECK_EQUAL(results.back().reverse_node_id, 1);
|
||||
{
|
||||
auto results = query.NearestPhantomNodes(input, 5);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
BOOST_CHECK_EQUAL(results.back().second.forward_node_id, 0);
|
||||
BOOST_CHECK_EQUAL(results.back().second.reverse_node_id, 1);
|
||||
}
|
||||
|
||||
results.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate( input, results, 5, 270, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 0);
|
||||
{
|
||||
auto results = query.NearestPhantomNodes(input, 5, 270, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 0);
|
||||
}
|
||||
|
||||
results.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate( input, results, 5, 45, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
BOOST_CHECK_EQUAL(results[0].forward_node_id, 1);
|
||||
BOOST_CHECK_EQUAL(results[0].reverse_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].forward_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].reverse_node_id, 1);
|
||||
{
|
||||
auto results = query.NearestPhantomNodes(input, 5, 45, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
BOOST_CHECK_EQUAL(results[0].second.forward_node_id, 1);
|
||||
BOOST_CHECK_EQUAL(results[0].second.reverse_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].second.forward_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].second.reverse_node_id, 1);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(input, 11000);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
}
|
||||
|
||||
std::vector<std::pair<PhantomNode, double>> distance_results;
|
||||
rtree.IncrementalFindPhantomNodeForCoordinateWithDistance( input, distance_results, 11000 );
|
||||
BOOST_CHECK_EQUAL(distance_results.size(), 2);
|
||||
|
||||
distance_results.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinateWithDistance( input, distance_results, 11000, 270, 10 );
|
||||
BOOST_CHECK_EQUAL(distance_results.size(), 0);
|
||||
|
||||
distance_results.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinateWithDistance( input, distance_results, 11000, 45, 10 );
|
||||
BOOST_CHECK_EQUAL(distance_results.size(), 2);
|
||||
BOOST_CHECK_EQUAL(distance_results[0].first.forward_node_id, 1);
|
||||
BOOST_CHECK_EQUAL(distance_results[0].first.reverse_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(distance_results[1].first.forward_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(distance_results[1].first.reverse_node_id, 1);
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(input, 11000, 270, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(input, 11000, 45, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
BOOST_CHECK_EQUAL(results[0].second.forward_node_id, 1);
|
||||
BOOST_CHECK_EQUAL(results[0].second.reverse_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].second.forward_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].second.reverse_node_id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../util/bearing.hpp"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(bearing)
|
||||
|
||||
// Verify that the bearing-bounds checking function behaves as expected
|
||||
BOOST_AUTO_TEST_CASE(bearing_range_test)
|
||||
{
|
||||
// Simple, non-edge-case checks
|
||||
BOOST_CHECK_EQUAL(true, bearing::CheckInBounds(45, 45, 10));
|
||||
BOOST_CHECK_EQUAL(true, bearing::CheckInBounds(35, 45, 10));
|
||||
BOOST_CHECK_EQUAL(true, bearing::CheckInBounds(55, 45, 10));
|
||||
|
||||
BOOST_CHECK_EQUAL(false, bearing::CheckInBounds(34, 45, 10));
|
||||
BOOST_CHECK_EQUAL(false, bearing::CheckInBounds(56, 45, 10));
|
||||
|
||||
BOOST_CHECK_EQUAL(false, bearing::CheckInBounds(34, 45, 10));
|
||||
BOOST_CHECK_EQUAL(false, bearing::CheckInBounds(56, 45, 10));
|
||||
|
||||
// When angle+limit goes > 360
|
||||
BOOST_CHECK_EQUAL(true, bearing::CheckInBounds(359, 355, 10));
|
||||
|
||||
// When angle-limit goes < 0
|
||||
BOOST_CHECK_EQUAL(true, bearing::CheckInBounds(359, 5, 10));
|
||||
BOOST_CHECK_EQUAL(false, bearing::CheckInBounds(354, 5, 10));
|
||||
BOOST_CHECK_EQUAL(false, bearing::CheckInBounds(16, 5, 10));
|
||||
|
||||
|
||||
// Checking other cases of wraparound
|
||||
BOOST_CHECK_EQUAL(true, bearing::CheckInBounds(359, -5, 10));
|
||||
BOOST_CHECK_EQUAL(false, bearing::CheckInBounds(344, -5, 10));
|
||||
BOOST_CHECK_EQUAL(false, bearing::CheckInBounds(6, -5, 10));
|
||||
|
||||
BOOST_CHECK_EQUAL(true, bearing::CheckInBounds(-1, 5, 10));
|
||||
BOOST_CHECK_EQUAL(false, bearing::CheckInBounds(-6, 5, 10));
|
||||
|
||||
BOOST_CHECK_EQUAL(true, bearing::CheckInBounds(-721, 5, 10));
|
||||
BOOST_CHECK_EQUAL(true, bearing::CheckInBounds(719, 5, 10));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE util tests
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
/*
|
||||
* This file will contain an automatically generated main function.
|
||||
*/
|
||||
Reference in New Issue
Block a user