Compare commits

...

19 Commits

Author SHA1 Message Date
Patrick Niklaus 6aed145dae [skip ci] Rephrased the API docs in terms of adding new types 2016-05-09 18:39:30 +02:00
Patrick Niklaus d15cc77b0b Merge pull request #2386 from oxidase/rtree-optimize-addition
Missing two commits in StaticRTree changes
2016-05-08 14:20:59 +02:00
Michael Krasnyk 24a75d37fb Approximate inverse Gudermannian function by a Padé approximant 2016-05-08 06:00:21 +02:00
Michael Krasnyk 7e80dae59b Fix MSVS build. 2016-05-08 06:00:21 +02:00
Patrick Niklaus 7316c48e9f Changelog entry for StaticRTree changes 2016-05-07 23:52:11 +02:00
Patrick Niklaus c520c7a24a Fix rtree benchmark 2016-05-07 23:52:11 +02:00
Patrick Niklaus 7564633045 Update SearchInBox to not copy TreeNode 2016-05-07 23:52:11 +02:00
Patrick Niklaus 7174c5d036 Make StaticRTree and facades const 2016-05-07 23:52:11 +02:00
Patrick Niklaus ddd128ce0e Only use const-ref for coordinate vector 2016-05-07 23:52:11 +02:00
Patrick Niklaus f5aa5c0769 Don't wrap StaticRTree in thread-specfic ptr 2016-05-07 23:52:11 +02:00
Michael Krasnyk 2acde49f0f Make LeafNode aligned to memory pages.
Changes:
* LeafNode is aligned to LEAF_PAGE_SIZE.
  Alignment brings 24 bytes memory overhead for 4096, but reduces
  cache misses rate.
* Unused m_element_count from leaf nodes file.
  The size is computed as m_leaves_region.size() / LEAF_PAGE_SIZE.
* Added try/catch for mmap exceptions messages.
2016-05-07 23:52:11 +02:00
Michael Krasnyk 8849015bbf Fix construct_multiple_levels_test
candidate_cache is removed because of failing test
make util-tests && ./unit_tests/util-tests --run_test=*/construct_multiple_levels_test
first bad commit: [9692be6f50] Add cache for CandidateSegments to reduce heap worke even more

Now SegmentIndex contains leaf index, object index and fixed_projected_coordinate
2016-05-07 23:52:11 +02:00
Michael Krasnyk 70cd7a94ec Fix memory mapping "Invalid argument" exception. 2016-05-07 23:52:11 +02:00
Patrick Niklaus 3984dea34b Use mmap in StaticRTree 2016-05-07 23:52:11 +02:00
Patrick Niklaus b11b471aa4 Move LoadLeafFromDisk to return by value 2016-05-07 23:52:11 +02:00
Patrick Niklaus 63754df4d4 Add cache for CandidateSegments to reduce heap worke even more 2016-05-07 23:52:11 +02:00
Patrick Niklaus e644424508 Only save TreeNode index in search tree x3 speedup 2016-05-07 23:52:11 +02:00
Patrick Niklaus 4f6eef3d16 Merge pull request #2376 from oxidase/fix/addition-to-2356
Addition to fix #2356
2016-05-07 12:47:28 +02:00
Michael Krasnyk e2e8104864 Addition to fix #2356
Updated unit tests for the Hint parser and
added emplacement of empty hints.
2016-05-07 09:47:32 +02:00
16 changed files with 304 additions and 355 deletions
+1
View File
@@ -16,6 +16,7 @@
- Infrastructure
- BREAKING: reordered internal instruction types. This breaks the **data format**
- BREAKING: Changed the on-disk encoding of the StaticRTree for better performance. This breaks the **data format**
- Fixes:
- Issue #2310: post-processing for local paths, fixes #2310
+3 -2
View File
@@ -421,7 +421,8 @@ step.
direction of travel immediately before the maneuver.
- `bearing_after`: The clockwise angle from true north to the
direction of travel immediately after the maneuver.
- `type` A string indicating the type of maneuver
- `type` A string indicating the type of maneuver. **new identifiers might be introduced without API change**
Types unknown to the client should be handled like the `turn` type, the existance of correct `modifier` values is guranteed.
| `type` | Description |
|-------------------|--------------------------------------------------------------|
@@ -476,7 +477,7 @@ step.
| `turn` or `end of road`| Indicates the number of intersections passed until the turn. Example instruction: `at the fourth intersection, turn left` |
New maneuver `type` and `modifier` and new properties (potentially depending on `type`) may be introduced in the future without an API version change.
New properties (potentially depending on `type`) may be introduced in the future without an API version change.
### Waypoint
+11 -11
View File
@@ -90,47 +90,47 @@ class BaseDataFacade
virtual extractor::TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0;
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
const util::Coordinate north_east) = 0;
const util::Coordinate north_east) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range) = 0;
const int bearing_range) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance) = 0;
const float max_distance) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) = 0;
const int bearing_range) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) = 0;
const int bearing_range) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) = 0;
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) const = 0;
virtual std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) = 0;
const double max_distance) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) = 0;
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance) = 0;
const double max_distance) const = 0;
virtual std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) = 0;
const int bearing_range) const = 0;
virtual std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) = 0;
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) const = 0;
virtual unsigned GetCheckSum() const = 0;
@@ -69,7 +69,7 @@ class InternalDataFacade final : public BaseDataFacade
std::unique_ptr<QueryGraph> m_query_graph;
std::string m_timestamp;
std::shared_ptr<util::ShM<util::Coordinate, false>::vector> m_coordinate_list;
util::ShM<util::Coordinate, false>::vector m_coordinate_list;
util::ShM<NodeID, false>::vector m_via_node_list;
util::ShM<unsigned, false>::vector m_name_ID_list;
util::ShM<extractor::guidance::TurnInstruction, false>::vector m_turn_instruction_list;
@@ -83,8 +83,8 @@ class InternalDataFacade final : public BaseDataFacade
util::ShM<std::string, false>::vector m_datasource_names;
extractor::ProfileProperties m_profile_properties;
boost::thread_specific_ptr<InternalRTree> m_static_rtree;
boost::thread_specific_ptr<InternalGeospatialQuery> m_geospatial_query;
std::unique_ptr<InternalRTree> m_static_rtree;
std::unique_ptr<InternalGeospatialQuery> m_geospatial_query;
boost::filesystem::path ram_index_path;
boost::filesystem::path file_index_path;
util::RangeTable<16, false> m_name_table;
@@ -139,12 +139,12 @@ class InternalDataFacade final : public BaseDataFacade
extractor::QueryNode current_node;
unsigned number_of_coordinates = 0;
nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
m_coordinate_list = std::make_shared<std::vector<util::Coordinate>>(number_of_coordinates);
m_coordinate_list.resize(number_of_coordinates);
for (unsigned i = 0; i < number_of_coordinates; ++i)
{
nodes_input_stream.read((char *)&current_node, sizeof(extractor::QueryNode));
m_coordinate_list->at(i) = util::Coordinate(current_node.lon, current_node.lat);
BOOST_ASSERT(m_coordinate_list->at(i).IsValid());
m_coordinate_list[i] = util::Coordinate(current_node.lon, current_node.lat);
BOOST_ASSERT(m_coordinate_list[i].IsValid());
}
boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary);
@@ -253,7 +253,7 @@ class InternalDataFacade final : public BaseDataFacade
void LoadRTree()
{
BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree");
m_static_rtree.reset(new InternalRTree(ram_index_path, file_index_path, m_coordinate_list));
m_geospatial_query.reset(
@@ -313,6 +313,9 @@ class InternalDataFacade final : public BaseDataFacade
util::SimpleLogger().Write() << "loading street names";
LoadStreetNames(config.names_data_path);
util::SimpleLogger().Write() << "loading rtree";
LoadRTree();
}
// search graph access
@@ -361,7 +364,7 @@ class InternalDataFacade final : public BaseDataFacade
// node and edge information access
util::Coordinate GetCoordinateOfNode(const unsigned id) const override final
{
return m_coordinate_list->at(id);
return m_coordinate_list[id];
}
extractor::guidance::TurnInstruction
@@ -376,13 +379,9 @@ class InternalDataFacade final : public BaseDataFacade
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
const util::Coordinate north_east) override final
const util::Coordinate north_east) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
const util::RectangleInt2D bbox{south_west.lon, north_east.lon, south_west.lat,
north_east.lat};
return m_geospatial_query->Search(bbox);
@@ -390,13 +389,9 @@ class InternalDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance) override final
const float max_distance) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance);
}
@@ -405,13 +400,9 @@ class InternalDataFacade final : public BaseDataFacade
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance,
bearing, bearing_range);
@@ -419,13 +410,9 @@ class InternalDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results) override final
const unsigned max_results) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results);
}
@@ -433,13 +420,9 @@ class InternalDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) override final
const double max_distance) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance);
}
@@ -448,13 +431,9 @@ class InternalDataFacade final : public BaseDataFacade
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, bearing,
bearing_range);
@@ -465,13 +444,9 @@ class InternalDataFacade final : public BaseDataFacade
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance,
bearing, bearing_range);
@@ -479,26 +454,18 @@ class InternalDataFacade final : public BaseDataFacade
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance) override final
const double max_distance) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance);
}
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate) override final
const util::Coordinate input_coordinate) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate);
@@ -508,13 +475,9 @@ class InternalDataFacade final : public BaseDataFacade
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance, bearing, bearing_range);
@@ -523,13 +486,9 @@ class InternalDataFacade final : public BaseDataFacade
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get())
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, bearing, bearing_range);
+49 -97
View File
@@ -55,7 +55,6 @@ class SharedDataFacade final : public BaseDataFacade
using SharedRTree =
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, true>::vector, true>;
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
using TimeStampedRTreePair = std::pair<unsigned, std::shared_ptr<SharedRTree>>;
using RTreeNode = SharedRTree::TreeNode;
storage::SharedDataLayout *data_layout;
@@ -71,9 +70,9 @@ class SharedDataFacade final : public BaseDataFacade
std::unique_ptr<storage::SharedMemory> m_layout_memory;
std::unique_ptr<storage::SharedMemory> m_large_memory;
std::string m_timestamp;
extractor::ProfileProperties* m_profile_properties;
extractor::ProfileProperties *m_profile_properties;
std::shared_ptr<util::ShM<util::Coordinate, true>::vector> m_coordinate_list;
util::ShM<util::Coordinate, true>::vector m_coordinate_list;
util::ShM<NodeID, true>::vector m_via_node_list;
util::ShM<unsigned, true>::vector m_name_ID_list;
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
@@ -89,8 +88,8 @@ class SharedDataFacade final : public BaseDataFacade
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
util::ShM<std::size_t, true>::vector m_datasource_name_lengths;
boost::thread_specific_ptr<std::pair<unsigned, std::shared_ptr<SharedRTree>>> m_static_rtree;
boost::thread_specific_ptr<SharedGeospatialQuery> m_geospatial_query;
std::unique_ptr<SharedRTree> m_static_rtree;
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
boost::filesystem::path file_index_path;
std::shared_ptr<util::RangeTable<16, true>> m_name_table;
@@ -104,8 +103,8 @@ class SharedDataFacade final : public BaseDataFacade
void LoadProfileProperties()
{
m_profile_properties =
data_layout->GetBlockPtr<extractor::ProfileProperties>(shared_memory, storage::SharedDataLayout::PROPERTIES);
m_profile_properties = data_layout->GetBlockPtr<extractor::ProfileProperties>(
shared_memory, storage::SharedDataLayout::PROPERTIES);
}
void LoadTimestamp()
@@ -120,17 +119,15 @@ class SharedDataFacade final : public BaseDataFacade
void LoadRTree()
{
BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree");
auto tree_ptr = data_layout->GetBlockPtr<RTreeNode>(
shared_memory, storage::SharedDataLayout::R_SEARCH_TREE);
m_static_rtree.reset(new TimeStampedRTreePair(
CURRENT_TIMESTAMP,
util::make_unique<SharedRTree>(
tree_ptr, data_layout->num_entries[storage::SharedDataLayout::R_SEARCH_TREE],
file_index_path, m_coordinate_list)));
m_static_rtree.reset(new SharedRTree(
tree_ptr, data_layout->num_entries[storage::SharedDataLayout::R_SEARCH_TREE],
file_index_path, m_coordinate_list));
m_geospatial_query.reset(
new SharedGeospatialQuery(*m_static_rtree->second, m_coordinate_list, *this));
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
void LoadGraph()
@@ -152,8 +149,7 @@ class SharedDataFacade final : public BaseDataFacade
{
auto coordinate_list_ptr = data_layout->GetBlockPtr<util::Coordinate>(
shared_memory, storage::SharedDataLayout::COORDINATE_LIST);
m_coordinate_list = util::make_unique<util::ShM<util::Coordinate, true>::vector>(
coordinate_list_ptr,
m_coordinate_list.reset(coordinate_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]);
auto travel_mode_list_ptr = data_layout->GetBlockPtr<extractor::TravelMode>(
@@ -165,10 +161,9 @@ class SharedDataFacade final : public BaseDataFacade
auto turn_instruction_list_ptr =
data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>(
shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION);
util::ShM<extractor::guidance::TurnInstruction, true>::vector
turn_instruction_list(
turn_instruction_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]);
util::ShM<extractor::guidance::TurnInstruction, true>::vector turn_instruction_list(
turn_instruction_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]);
m_turn_instruction_list = std::move(turn_instruction_list);
auto name_id_list_ptr = data_layout->GetBlockPtr<unsigned>(
@@ -234,9 +229,9 @@ class SharedDataFacade final : public BaseDataFacade
auto geometries_list_ptr =
data_layout->GetBlockPtr<extractor::CompressedEdgeContainer::CompressedEdge>(
shared_memory, storage::SharedDataLayout::GEOMETRIES_LIST);
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector
geometry_list(geometries_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_LIST]);
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector geometry_list(
geometries_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_LIST]);
m_geometry_list = std::move(geometry_list);
auto datasources_list_ptr = data_layout->GetBlockPtr<uint8_t>(
@@ -354,15 +349,13 @@ class SharedDataFacade final : public BaseDataFacade
LoadNames();
LoadCoreInformation();
LoadProfileProperties();
LoadRTree();
util::SimpleLogger().Write() << "number of geometries: "
<< m_coordinate_list->size();
for (unsigned i = 0; i < m_coordinate_list->size(); ++i)
<< m_coordinate_list.size();
for (unsigned i = 0; i < m_coordinate_list.size(); ++i)
{
if (!GetCoordinateOfNode(i).IsValid())
{
util::SimpleLogger().Write() << "coordinate " << i << " not valid";
}
BOOST_ASSERT(GetCoordinateOfNode(i).IsValid());
}
}
util::SimpleLogger().Write(logDEBUG) << "Releasing exclusive lock";
@@ -415,7 +408,7 @@ class SharedDataFacade final : public BaseDataFacade
// node and edge information access
util::Coordinate GetCoordinateOfNode(const NodeID id) const override final
{
return m_coordinate_list->at(id);
return m_coordinate_list[id];
}
virtual void GetUncompressedGeometry(const EdgeID id,
@@ -466,13 +459,9 @@ class SharedDataFacade final : public BaseDataFacade
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
const util::Coordinate north_east) override final
const util::Coordinate north_east) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
const util::RectangleInt2D bbox{south_west.lon, north_east.lon, south_west.lat,
north_east.lat};
return m_geospatial_query->Search(bbox);
@@ -480,13 +469,9 @@ class SharedDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance) override final
const float max_distance) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance);
}
@@ -495,13 +480,9 @@ class SharedDataFacade final : public BaseDataFacade
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const float max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance,
bearing, bearing_range);
@@ -509,13 +490,9 @@ class SharedDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results) override final
const unsigned max_results) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results);
}
@@ -523,13 +500,9 @@ class SharedDataFacade final : public BaseDataFacade
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance) override final
const double max_distance) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance);
}
@@ -538,13 +511,9 @@ class SharedDataFacade final : public BaseDataFacade
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, bearing,
bearing_range);
@@ -555,26 +524,18 @@ class SharedDataFacade final : public BaseDataFacade
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance,
bearing, bearing_range);
}
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate) override final
const util::Coordinate input_coordinate) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate);
@@ -582,13 +543,9 @@ class SharedDataFacade final : public BaseDataFacade
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance) override final
const double max_distance) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance);
@@ -598,13 +555,9 @@ class SharedDataFacade final : public BaseDataFacade
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, max_distance, bearing, bearing_range);
@@ -613,13 +566,9 @@ class SharedDataFacade final : public BaseDataFacade
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const int bearing,
const int bearing_range) override final
const int bearing_range) const override final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
BOOST_ASSERT(m_geospatial_query.get());
}
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
input_coordinate, bearing, bearing_range);
@@ -710,7 +659,10 @@ class SharedDataFacade final : public BaseDataFacade
std::string GetTimestamp() const override final { return m_timestamp; }
bool GetContinueStraightDefault() const override final { return m_profile_properties->continue_straight_at_waypoint; }
bool GetContinueStraightDefault() const override final
{
return m_profile_properties->continue_straight_at_waypoint;
}
};
}
}
+19 -19
View File
@@ -22,7 +22,7 @@ namespace engine
// Implements complex queries on top of an RTree and builds PhantomNodes from it.
//
// Only holds a weak reference on the RTree!
// Only holds a weak reference on the RTree and coordinates!
template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
{
using EdgeData = typename RTreeT::EdgeData;
@@ -31,9 +31,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
public:
GeospatialQuery(RTreeT &rtree_,
std::shared_ptr<CoordinateList> coordinates_,
const CoordinateList &coordinates_,
DataFacadeT &datafacade_)
: rtree(rtree_), coordinates(std::move(coordinates_)), datafacade(datafacade_)
: rtree(rtree_), coordinates(coordinates_), datafacade(datafacade_)
{
}
@@ -45,7 +45,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Returns nearest PhantomNodes in the given bearing range within max_distance.
// Does not filter by small/big component!
std::vector<PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const double max_distance)
NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const double max_distance) const
{
auto results =
rtree.Nearest(input_coordinate,
@@ -68,7 +68,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodesInRange(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range)
const int bearing_range) const
{
auto results = rtree.Nearest(
input_coordinate,
@@ -91,7 +91,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const int bearing,
const int bearing_range)
const int bearing_range) const
{
auto results =
rtree.Nearest(input_coordinate,
@@ -115,7 +115,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const unsigned max_results,
const double max_distance,
const int bearing,
const int bearing_range)
const int bearing_range) const
{
auto results =
rtree.Nearest(input_coordinate,
@@ -136,7 +136,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Returns max_results nearest PhantomNodes.
// Does not filter by small/big component!
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results)
NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results) const
{
auto results =
rtree.Nearest(input_coordinate,
@@ -157,7 +157,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const unsigned max_results,
const double max_distance)
const double max_distance) const
{
auto results =
rtree.Nearest(input_coordinate,
@@ -179,7 +179,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// a second phantom node is return that is the nearest coordinate in a big component.
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance)
const double max_distance) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -216,7 +216,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// 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.
std::pair<PhantomNode, PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate)
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -251,7 +251,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// 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.
std::pair<PhantomNode, PhantomNode> NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate input_coordinate, const int bearing, const int bearing_range)
const util::Coordinate input_coordinate, const int bearing, const int bearing_range) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -297,7 +297,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
const double max_distance,
const int bearing,
const int bearing_range)
const int bearing_range) const
{
bool has_small_component = false;
bool has_big_component = false;
@@ -360,7 +360,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
double ratio;
const auto current_perpendicular_distance =
util::coordinate_calculation::perpendicularDistance(
coordinates->at(data.u), coordinates->at(data.v), input_coordinate,
coordinates[data.u], coordinates[data.v], input_coordinate,
point_on_segment, ratio);
// Find the node-based-edge that this belongs to, and directly
@@ -418,7 +418,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
bool CheckSegmentDistance(const Coordinate input_coordinate,
const CandidateSegment &segment,
const double max_distance)
const double max_distance) const
{
BOOST_ASSERT(segment.data.forward_segment_id.id != SPECIAL_SEGMENTID ||
!segment.data.forward_segment_id.enabled);
@@ -434,7 +434,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
std::pair<bool, bool> CheckSegmentBearing(const CandidateSegment &segment,
const int filter_bearing,
const int filter_bearing_range)
const int filter_bearing_range) const
{
BOOST_ASSERT(segment.data.forward_segment_id.id != SPECIAL_SEGMENTID ||
!segment.data.forward_segment_id.enabled);
@@ -442,7 +442,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
!segment.data.reverse_segment_id.enabled);
const double forward_edge_bearing = util::coordinate_calculation::bearing(
coordinates->at(segment.data.u), coordinates->at(segment.data.v));
coordinates[segment.data.u], coordinates[segment.data.v]);
const double backward_edge_bearing = (forward_edge_bearing + 180) > 360
? (forward_edge_bearing - 180)
@@ -459,8 +459,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
return std::make_pair(forward_bearing_valid, backward_bearing_valid);
}
RTreeT &rtree;
const std::shared_ptr<CoordinateList> coordinates;
const RTreeT &rtree;
const CoordinateList &coordinates;
DataFacadeT &datafacade;
};
}
@@ -75,11 +75,15 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
BaseParametersGrammar(qi::rule<Iterator, Signature> &root_rule)
: BaseParametersGrammar::base_type(root_rule)
{
const auto add_hint = [](engine::api::BaseParameters &base_parameters, const std::string &hint_string)
const auto add_hint = [](engine::api::BaseParameters &base_parameters, const boost::optional<std::string> &hint_string)
{
if (hint_string.size() > 0)
if (hint_string)
{
base_parameters.hints.emplace_back(engine::Hint::FromBase64(hint_string));
base_parameters.hints.emplace_back(engine::Hint::FromBase64(hint_string.get()));
}
else
{
base_parameters.hints.emplace_back(boost::none);
}
};
@@ -134,7 +138,7 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
hints_rule
= qi::lit("hints=")
> -qi::as_string[qi::repeat(engine::ENCODED_HINT_SIZE)[base64_char]][ph::bind(add_hint, qi::_r1, qi::_1)] % ';'
> (-qi::as_string[qi::repeat(engine::ENCODED_HINT_SIZE)[base64_char]])[ph::bind(add_hint, qi::_r1, qi::_1)] % ';'
;
bearings_rule
@@ -55,6 +55,12 @@ template <typename DataT> class SharedMemoryWrapper
SharedMemoryWrapper(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
void reset(DataT *ptr, std::size_t size)
{
m_ptr = ptr;
m_size = size;
}
DataT &at(const std::size_t index) { return m_ptr[index]; }
const DataT &at(const std::size_t index) const { return m_ptr[index]; }
@@ -101,6 +107,12 @@ template <> class SharedMemoryWrapper<bool>
return m_ptr[bucket] & (1u << offset);
}
void reset(unsigned *ptr, std::size_t size)
{
m_ptr = ptr;
m_size = size;
}
std::size_t size() const { return m_size; }
bool empty() const { return 0 == size(); }
+83 -101
View File
@@ -17,6 +17,7 @@
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <tbb/parallel_for.h>
#include <tbb/parallel_sort.h>
@@ -42,8 +43,8 @@ namespace util
template <class EdgeDataT,
class CoordinateListT = std::vector<Coordinate>,
bool UseSharedMemory = false,
std::uint32_t BRANCHING_FACTOR = 64,
std::uint32_t LEAF_NODE_SIZE = 256>
std::uint32_t BRANCHING_FACTOR = 128,
std::uint32_t LEAF_PAGE_SIZE = 4096>
class StaticRTree
{
public:
@@ -51,6 +52,10 @@ class StaticRTree
using EdgeData = EdgeDataT;
using CoordinateList = CoordinateListT;
static_assert(LEAF_PAGE_SIZE >= sizeof(uint32_t) + sizeof(EdgeDataT), "LEAF_PAGE_SIZE is too small");
static_assert(((LEAF_PAGE_SIZE - 1) & LEAF_PAGE_SIZE) == 0, "LEAF_PAGE_SIZE is not a power of 2");
static constexpr std::uint32_t LEAF_NODE_SIZE = (LEAF_PAGE_SIZE - sizeof(uint32_t)) / sizeof(EdgeDataT);
struct CandidateSegment
{
Coordinate fixed_projected_coordinate;
@@ -69,9 +74,11 @@ class StaticRTree
struct LeafNode
{
LeafNode() : object_count(0), objects() {}
uint32_t object_count;
std::uint32_t object_count;
std::array<EdgeDataT, LEAF_NODE_SIZE> objects;
unsigned char leaf_page_padding[LEAF_PAGE_SIZE - sizeof(std::uint32_t) - sizeof(std::array<EdgeDataT, LEAF_NODE_SIZE>)];
};
static_assert(sizeof(LeafNode) == LEAF_PAGE_SIZE, "LeafNode size does not fit the page size");
private:
struct WrappedInputElement
@@ -93,7 +100,9 @@ class StaticRTree
}
};
using QueryNodeType = mapbox::util::variant<TreeNode, CandidateSegment>;
struct TreeIndex { std::uint32_t index; };
struct SegmentIndex { std::uint32_t index; std::uint32_t object; Coordinate fixed_projected_coordinate; };
using QueryNodeType = mapbox::util::variant<TreeIndex, SegmentIndex>;
struct QueryCandidate
{
inline bool operator<(const QueryCandidate &other) const
@@ -107,10 +116,11 @@ class StaticRTree
};
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
uint64_t m_element_count;
const std::string m_leaf_node_filename;
std::shared_ptr<CoordinateListT> m_coordinate_list;
boost::filesystem::ifstream leaves_stream;
const CoordinateListT& m_coordinate_list;
boost::iostreams::mapped_file_source m_leaves_region;
// read-only view of leaves
typename ShM<const LeafNode, true>::vector m_leaves;
public:
StaticRTree(const StaticRTree &) = delete;
@@ -122,15 +132,16 @@ class StaticRTree
const std::string &tree_node_filename,
const std::string &leaf_node_filename,
const std::vector<CoordinateT> &coordinate_list)
: m_element_count(input_data_vector.size()), m_leaf_node_filename(leaf_node_filename)
: m_coordinate_list(coordinate_list)
{
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
const uint64_t element_count = input_data_vector.size();
std::vector<WrappedInputElement> input_wrapper_vector(element_count);
// generate auxiliary vector of hilbert-values
tbb::parallel_for(
tbb::blocked_range<uint64_t>(0, m_element_count),
tbb::blocked_range<uint64_t>(0, element_count),
[&input_data_vector, &input_wrapper_vector,
&coordinate_list](const tbb::blocked_range<uint64_t> &range)
this](const tbb::blocked_range<uint64_t> &range)
{
for (uint64_t element_counter = range.begin(), end = range.end();
element_counter != end; ++element_counter)
@@ -141,11 +152,11 @@ class StaticRTree
EdgeDataT const &current_element = input_data_vector[element_counter];
// Get Hilbert-Value for centroid in mercartor projection
BOOST_ASSERT(current_element.u < coordinate_list.size());
BOOST_ASSERT(current_element.v < coordinate_list.size());
BOOST_ASSERT(current_element.u < m_coordinate_list.size());
BOOST_ASSERT(current_element.v < m_coordinate_list.size());
Coordinate current_centroid = coordinate_calculation::centroid(
coordinate_list[current_element.u], coordinate_list[current_element.v]);
m_coordinate_list[current_element.u], m_coordinate_list[current_element.v]);
current_centroid.lat =
FixedLatitude(COORDINATE_PRECISION *
web_mercator::latToY(toFloating(current_centroid.lat)));
@@ -156,7 +167,6 @@ class StaticRTree
// open leaf file
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
leaf_node_file.write((char *)&m_element_count, sizeof(uint64_t));
// sort the hilbert-value representatives
tbb::parallel_sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
@@ -164,7 +174,7 @@ class StaticRTree
// pack M elements into leaf node and write to leaf file
uint64_t processed_objects_count = 0;
while (processed_objects_count < m_element_count)
while (processed_objects_count < element_count)
{
LeafNode current_leaf;
@@ -172,7 +182,7 @@ class StaticRTree
for (std::uint32_t current_element_index = 0; LEAF_NODE_SIZE > current_element_index;
++current_element_index)
{
if (m_element_count > (processed_objects_count + current_element_index))
if (element_count > (processed_objects_count + current_element_index))
{
std::uint32_t index_of_next_object =
input_wrapper_vector[processed_objects_count + current_element_index]
@@ -185,7 +195,7 @@ class StaticRTree
// generate tree node that resemble the objects in leaf and store it for next level
InitializeMBRectangle(current_node.minimum_bounding_rectangle, current_leaf.objects,
current_leaf.object_count, coordinate_list);
current_leaf.object_count, m_coordinate_list);
current_node.child_is_on_disk = true;
current_node.children[0] = tree_nodes_in_level.size();
tree_nodes_in_level.emplace_back(current_node);
@@ -194,6 +204,8 @@ class StaticRTree
leaf_node_file.write((char *)&current_leaf, sizeof(current_leaf));
processed_objects_count += current_leaf.object_count;
}
leaf_node_file.flush();
leaf_node_file.close();
std::uint32_t processing_level = 0;
while (1 < tree_nodes_in_level.size())
@@ -258,16 +270,16 @@ class StaticRTree
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
tree_node_file.write((char *)&size_of_tree, sizeof(std::uint32_t));
tree_node_file.write((char *)&m_search_tree[0], sizeof(TreeNode) * size_of_tree);
MapLeafNodesFile(leaf_node_filename);
}
explicit StaticRTree(const boost::filesystem::path &node_file,
const boost::filesystem::path &leaf_file,
const std::shared_ptr<CoordinateListT> coordinate_list)
: m_leaf_node_filename(leaf_file.string())
const CoordinateListT& coordinate_list)
: m_coordinate_list(coordinate_list)
{
// open tree node file and load into RAM.
m_coordinate_list = coordinate_list;
if (!boost::filesystem::exists(node_file))
{
throw exception("ram index file does not exist");
@@ -287,44 +299,34 @@ class StaticRTree
tree_node_file.read((char *)&m_search_tree[0], sizeof(TreeNode) * tree_size);
}
// open leaf node file and store thread specific pointer
if (!boost::filesystem::exists(leaf_file))
{
throw exception("mem index file does not exist");
}
if (0 == boost::filesystem::file_size(leaf_file))
{
throw exception("mem index file is empty");
}
leaves_stream.open(leaf_file, std::ios::binary);
leaves_stream.read((char *)&m_element_count, sizeof(uint64_t));
MapLeafNodesFile(leaf_file);
}
explicit StaticRTree(TreeNode *tree_node_ptr,
const uint64_t number_of_nodes,
const boost::filesystem::path &leaf_file,
std::shared_ptr<CoordinateListT> coordinate_list)
: m_search_tree(tree_node_ptr, number_of_nodes), m_leaf_node_filename(leaf_file.string()),
m_coordinate_list(std::move(coordinate_list))
const CoordinateListT& coordinate_list)
: m_search_tree(tree_node_ptr, number_of_nodes)
, m_coordinate_list(coordinate_list)
{
// open leaf node file and store thread specific pointer
if (!boost::filesystem::exists(leaf_file))
{
throw exception("mem index file does not exist");
}
if (0 == boost::filesystem::file_size(leaf_file))
{
throw exception("mem index file is empty");
}
MapLeafNodesFile(leaf_file);
}
leaves_stream.open(leaf_file, std::ios::binary);
leaves_stream.read((char *)&m_element_count, sizeof(uint64_t));
void MapLeafNodesFile(const boost::filesystem::path &leaf_file)
{
// open leaf node file and return a pointer to the mapped leaves data
try {
m_leaves_region.open(leaf_file);
std::size_t num_leaves = m_leaves_region.size() / sizeof(LeafNode);
m_leaves.reset(reinterpret_cast<const LeafNode*>(m_leaves_region.data()), num_leaves);
} catch (std::exception& exc) {
throw exception(boost::str(boost::format("Leaf file %1% mapping failed: %2%") % leaf_file % exc.what()));
}
}
/* Returns all features inside the bounding box.
Rectangle needs to be projected!*/
std::vector<EdgeDataT> SearchInBox(const Rectangle &search_rectangle)
std::vector<EdgeDataT> SearchInBox(const Rectangle &search_rectangle) const
{
const Rectangle projected_rectangle{
search_rectangle.min_lon, search_rectangle.max_lon,
@@ -334,19 +336,17 @@ class StaticRTree
web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.max_lat)))})};
std::vector<EdgeDataT> results;
std::queue<TreeNode> traversal_queue;
traversal_queue.push(m_search_tree[0]);
std::queue<std::uint32_t> traversal_queue;
traversal_queue.push(0);
while (!traversal_queue.empty())
{
auto const current_tree_node = traversal_queue.front();
auto const &current_tree_node = m_search_tree[traversal_queue.front()];
traversal_queue.pop();
if (current_tree_node.child_is_on_disk)
{
LeafNode current_leaf_node;
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
const LeafNode& current_leaf_node = m_leaves[current_tree_node.children[0]];
for (const auto i : irange(0u, current_leaf_node.object_count))
{
@@ -354,14 +354,14 @@ class StaticRTree
// we don't need to project the coordinates here,
// because we use the unprojected rectangle to test against
const Rectangle bbox{std::min((*m_coordinate_list)[current_edge.u].lon,
(*m_coordinate_list)[current_edge.v].lon),
std::max((*m_coordinate_list)[current_edge.u].lon,
(*m_coordinate_list)[current_edge.v].lon),
std::min((*m_coordinate_list)[current_edge.u].lat,
(*m_coordinate_list)[current_edge.v].lat),
std::max((*m_coordinate_list)[current_edge.u].lat,
(*m_coordinate_list)[current_edge.v].lat)};
const Rectangle bbox{std::min(m_coordinate_list[current_edge.u].lon,
m_coordinate_list[current_edge.v].lon),
std::max(m_coordinate_list[current_edge.u].lon,
m_coordinate_list[current_edge.v].lon),
std::min(m_coordinate_list[current_edge.u].lat,
m_coordinate_list[current_edge.v].lat),
std::max(m_coordinate_list[current_edge.u].lat,
m_coordinate_list[current_edge.v].lat)};
// use the _unprojected_ input rectangle here
if (bbox.Intersects(search_rectangle))
@@ -382,7 +382,7 @@ class StaticRTree
if (child_rectangle.Intersects(projected_rectangle))
{
traversal_queue.push(m_search_tree[child_id]);
traversal_queue.push(child_id);
}
}
}
@@ -391,7 +391,7 @@ class StaticRTree
}
// Override filter and terminator for the desired behaviour.
std::vector<EdgeDataT> Nearest(const Coordinate input_coordinate, const std::size_t max_results)
std::vector<EdgeDataT> Nearest(const Coordinate input_coordinate, const std::size_t max_results) const
{
return Nearest(input_coordinate,
[](const CandidateSegment &)
@@ -407,7 +407,7 @@ class StaticRTree
// Override filter and terminator for the desired behaviour.
template <typename FilterT, typename TerminationT>
std::vector<EdgeDataT>
Nearest(const Coordinate input_coordinate, const FilterT filter, const TerminationT terminate)
Nearest(const Coordinate input_coordinate, const FilterT filter, const TerminationT terminate) const
{
std::vector<EdgeDataT> results;
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
@@ -415,17 +415,17 @@ class StaticRTree
// initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue;
traversal_queue.push(QueryCandidate{0, m_search_tree[0]});
traversal_queue.push(QueryCandidate{0, TreeIndex{0}});
while (!traversal_queue.empty())
{
QueryCandidate current_query_node = traversal_queue.top();
traversal_queue.pop();
if (current_query_node.node.template is<TreeNode>())
if (current_query_node.node.template is<TreeIndex>())
{ // current object is a tree node
const TreeNode &current_tree_node =
current_query_node.node.template get<TreeNode>();
m_search_tree[current_query_node.node.template get<TreeIndex>().index];
if (current_tree_node.child_is_on_disk)
{
ExploreLeafNode(current_tree_node.children[0], fixed_projected_coordinate,
@@ -439,7 +439,9 @@ class StaticRTree
else
{
// inspecting an actual road segment
auto &current_candidate = current_query_node.node.template get<CandidateSegment>();
const auto &segment_index = current_query_node.node.template get<SegmentIndex>();
auto edge_data = m_leaves[segment_index.index].objects[segment_index.object];
const auto &current_candidate = CandidateSegment{segment_index.fixed_projected_coordinate, edge_data};
// to allow returns of no-results if too restrictive filtering, this needs to be done here
// even though performance would indicate that we want to stop after adding the first candidate
@@ -454,11 +456,11 @@ class StaticRTree
{
continue;
}
current_candidate.data.forward_segment_id.enabled &= use_segment.first;
current_candidate.data.reverse_segment_id.enabled &= use_segment.second;
edge_data.forward_segment_id.enabled &= use_segment.first;
edge_data.reverse_segment_id.enabled &= use_segment.second;
// store phantom node in result vector
results.push_back(std::move(current_candidate.data));
results.push_back(std::move(edge_data));
}
}
@@ -470,17 +472,16 @@ class StaticRTree
void ExploreLeafNode(const std::uint32_t leaf_id,
const Coordinate projected_input_coordinate_fixed,
const FloatCoordinate &projected_input_coordinate,
QueueT &traversal_queue)
QueueT &traversal_queue) const
{
LeafNode current_leaf_node;
LoadLeafFromDisk(leaf_id, current_leaf_node);
const LeafNode& current_leaf_node = m_leaves[leaf_id];
// current object represents a block on disk
for (const auto i : irange(0u, current_leaf_node.object_count))
{
const auto &current_edge = current_leaf_node.objects[i];
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]);
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) =
@@ -491,16 +492,14 @@ class StaticRTree
projected_input_coordinate_fixed, projected_nearest);
// distance must be non-negative
BOOST_ASSERT(0. <= squared_distance);
traversal_queue.push(
QueryCandidate{squared_distance, CandidateSegment{Coordinate{projected_nearest},
std::move(current_edge)}});
traversal_queue.push(QueryCandidate{squared_distance, SegmentIndex{leaf_id, i, Coordinate{projected_nearest}}});
}
}
template <class QueueT>
void ExploreTreeNode(const TreeNode &parent,
const Coordinate fixed_projected_input_coordinate,
QueueT &traversal_queue)
QueueT &traversal_queue) const
{
for (std::uint32_t i = 0; i < parent.child_count; ++i)
{
@@ -510,27 +509,10 @@ class StaticRTree
const auto squared_lower_bound_to_element =
child_rectangle.GetMinSquaredDist(fixed_projected_input_coordinate);
traversal_queue.push(
QueryCandidate{squared_lower_bound_to_element, m_search_tree[child_id]});
QueryCandidate{squared_lower_bound_to_element, TreeIndex{static_cast<std::uint32_t>(child_id)}});
}
}
inline void LoadLeafFromDisk(const std::uint32_t leaf_id, LeafNode &result_node)
{
if (!leaves_stream.is_open())
{
leaves_stream.open(m_leaf_node_filename, std::ios::in | std::ios::binary);
}
if (!leaves_stream.good())
{
throw exception("Could not read from leaf file.");
}
const uint64_t seek_pos = sizeof(uint64_t) + leaf_id * sizeof(LeafNode);
leaves_stream.seekg(seek_pos);
BOOST_ASSERT_MSG(leaves_stream.good(), "Seeking to position in leaf file failed.");
leaves_stream.read((char *)&result_node, sizeof(LeafNode));
BOOST_ASSERT_MSG(leaves_stream.good(), "Reading from leaf file failed.");
}
template <typename CoordinateT>
void InitializeMBRectangle(Rectangle &rectangle,
const std::array<EdgeDataT, LEAF_NODE_SIZE> &objects,
+27 -2
View File
@@ -35,7 +35,7 @@ inline FloatLatitude yToLat(const double y)
const double normalized_lat =
detail::RAD_TO_DEGREE * 2. * std::atan(std::exp(clamped_y * detail::DEGREE_TO_RAD));
return FloatLatitude(normalized_lat - 90.);
return FloatLatitude(std::round(normalized_lat * COORDINATE_PRECISION) / COORDINATE_PRECISION - 90.);
}
inline double latToY(const FloatLatitude latitude)
@@ -47,6 +47,31 @@ inline double latToY(const FloatLatitude latitude)
return clamped_y;
}
template<typename T>
constexpr double horner(double, T an) { return an; }
template<typename T, typename... U>
constexpr double horner(double x, T an, U ...a) { return horner(x, a...) * x + an; }
inline double latToYapprox(const FloatLatitude latitude)
{
if (latitude < FloatLatitude(-70.) || latitude > FloatLatitude(70.))
return latToY(latitude);
// Approximate the inverse Gudermannian function with the Padé approximant [11/11]: deg → deg
// Coefficients are computed for the argument range [-70°,70°] by Remez algorithm |err|_∞=3.387e-12
const auto x = static_cast<double>(latitude);
return
horner(x, 0.00000000000000000000000000e+00, 1.00000000000089108431373566e+00, 2.34439410386997223035693483e-06,
-3.21291701673364717170998957e-04, -6.62778508496089940141103135e-10, 3.68188055470304769936079078e-08,
6.31192702320492485752941578e-14, -1.77274453235716299127325443e-12, -2.24563810831776747318521450e-18,
3.13524754818073129982475171e-17, 2.09014225025314211415458228e-23, -9.82938075991732185095509716e-23) /
horner(x, 1.00000000000000000000000000e+00, 2.34439410398970701719081061e-06, -3.72061271627251952928813333e-04,
-7.81802389685429267252612620e-10, 5.18418724186576447072888605e-08, 9.37468561198098681003717477e-14,
-3.30833288607921773936702558e-12, -4.78446279888774903983338274e-18, 9.32999229169156878168234191e-17,
9.17695141954265959600965170e-23, -8.72130728982012387640166055e-22, -3.23083224835967391884404730e-28);
}
inline FloatLatitude clamp(const FloatLatitude lat)
{
return std::max(std::min(lat, FloatLatitude(detail::MAX_LATITUDE)),
@@ -87,7 +112,7 @@ inline double degreeToPixel(FloatLatitude lat, unsigned zoom)
inline FloatCoordinate fromWGS84(const FloatCoordinate &wgs84_coordinate)
{
return {wgs84_coordinate.lon, FloatLatitude{latToY(wgs84_coordinate.lat)}};
return {wgs84_coordinate.lon, FloatLatitude{latToYapprox(wgs84_coordinate.lat)}};
}
inline FloatCoordinate toWGS84(const FloatCoordinate &mercator_coordinate)
+3 -4
View File
@@ -26,22 +26,21 @@ constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
using RTreeLeaf = extractor::EdgeBasedNode;
using CoordinateListPtr = std::shared_ptr<std::vector<util::Coordinate>>;
using BenchStaticRTree =
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, false>::vector, false>;
CoordinateListPtr loadCoordinates(const boost::filesystem::path &nodes_file)
std::vector<util::Coordinate> loadCoordinates(const boost::filesystem::path &nodes_file)
{
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
extractor::QueryNode current_node;
unsigned coordinate_count = 0;
nodes_input_stream.read((char *)&coordinate_count, sizeof(unsigned));
auto coords = std::make_shared<std::vector<Coordinate>>(coordinate_count);
std::vector<util::Coordinate> coords(coordinate_count);
for (unsigned i = 0; i < coordinate_count; ++i)
{
nodes_input_stream.read((char *)&current_node, sizeof(extractor::QueryNode));
coords->at(i) = util::Coordinate(current_node.lon, current_node.lat);
coords[i] = util::Coordinate(current_node.lon, current_node.lat);
}
return coords;
}
+5 -5
View File
@@ -330,16 +330,16 @@ std::size_t Contractor::LoadEdgeExpandedGraph(
using LeafNode = util::StaticRTree<extractor::EdgeBasedNode>::LeafNode;
std::ifstream leaf_node_file(rtree_leaf_filename, std::ios::binary | std::ios::in);
std::ifstream leaf_node_file(rtree_leaf_filename, std::ios::binary | std::ios::in | std::ios::ate);
if (!leaf_node_file)
{
throw util::exception("Failed to open " + rtree_leaf_filename);
}
uint64_t m_element_count;
leaf_node_file.read((char *)&m_element_count, sizeof(uint64_t));
std::size_t leaf_nodes_count = leaf_node_file.tellg() / sizeof(LeafNode);
leaf_node_file.seekg(0, std::ios::beg);
LeafNode current_node;
while (m_element_count > 0)
while (leaf_nodes_count > 0)
{
leaf_node_file.read(reinterpret_cast<char *>(&current_node), sizeof(current_node));
@@ -435,7 +435,7 @@ std::size_t Contractor::LoadEdgeExpandedGraph(
}
}
}
m_element_count -= current_node.object_count;
--leaf_nodes_count;
}
}
+3 -3
View File
@@ -563,9 +563,9 @@ void Extractor::BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
node_based_edge_list.resize(new_size);
TIMER_START(construction);
util::StaticRTree<EdgeBasedNode> rtree(node_based_edge_list, config.rtree_nodes_output_path,
config.rtree_leafs_output_path,
internal_to_external_node_map);
util::StaticRTree<EdgeBasedNode, std::vector<QueryNode>> rtree(
node_based_edge_list, config.rtree_nodes_output_path, config.rtree_leafs_output_path,
internal_to_external_node_map);
TIMER_STOP(construction);
util::SimpleLogger().Write() << "finished r-tree construction in " << TIMER_SEC(construction)
+11 -11
View File
@@ -78,7 +78,7 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
return TRAVEL_MODE_INACCESSIBLE;
}
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate /* south_west */,
const util::Coordinate /*north_east */) override
const util::Coordinate /*north_east */) const override
{
return {};
}
@@ -87,14 +87,14 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/,
const float /*max_distance*/,
const int /*bearing*/,
const int /*bearing_range*/) override
const int /*bearing_range*/) const override
{
return {};
}
std::vector<engine::PhantomNodeWithDistance>
NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/,
const float /*max_distance*/) override
const float /*max_distance*/) const override
{
return {};
}
@@ -104,7 +104,7 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
const unsigned /*max_results*/,
const double /*max_distance*/,
const int /*bearing*/,
const int /*bearing_range*/) override
const int /*bearing_range*/) const override
{
return {};
}
@@ -113,14 +113,14 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
const unsigned /*max_results*/,
const int /*bearing*/,
const int /*bearing_range*/) override
const int /*bearing_range*/) const override
{
return {};
}
std::vector<engine::PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
const unsigned /*max_results*/) override
const unsigned /*max_results*/) const override
{
return {};
}
@@ -128,21 +128,21 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
std::vector<engine::PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
const unsigned /*max_results*/,
const double /*max_distance*/) override
const double /*max_distance*/) const override
{
return {};
}
std::pair<engine::PhantomNode, engine::PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(
const util::Coordinate /*input_coordinate*/) override
const util::Coordinate /*input_coordinate*/) const override
{
return {};
}
std::pair<engine::PhantomNode, engine::PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
const double /*max_distance*/) override
const double /*max_distance*/) const override
{
return {};
}
@@ -151,7 +151,7 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
const double /*max_distance*/,
const int /*bearing*/,
const int /*bearing_range*/) override
const int /*bearing_range*/) const override
{
return {};
}
@@ -159,7 +159,7 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
std::pair<engine::PhantomNode, engine::PhantomNode>
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
const int /*bearing*/,
const int /*bearing_range*/) override
const int /*bearing_range*/) const override
{
return {};
};
+19 -4
View File
@@ -44,6 +44,8 @@ BOOST_AUTO_TEST_CASE(invalid_route_urls)
32UL);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&hints=foo"),
29UL);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&hints=;;; ;"),
32UL);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&geometries=foo"),
34UL);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?overview=false&overview=foo"),
@@ -88,6 +90,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
CHECK_EQUAL_RANGE(reference_1.bearings, result_1->bearings);
CHECK_EQUAL_RANGE(reference_1.radiuses, result_1->radiuses);
CHECK_EQUAL_RANGE(reference_1.coordinates, result_1->coordinates);
CHECK_EQUAL_RANGE(reference_1.hints, result_1->hints);
RouteParameters reference_2{};
reference_2.alternatives = true;
@@ -104,6 +107,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
CHECK_EQUAL_RANGE(reference_2.bearings, result_2->bearings);
CHECK_EQUAL_RANGE(reference_2.radiuses, result_2->radiuses);
CHECK_EQUAL_RANGE(reference_2.coordinates, result_2->coordinates);
CHECK_EQUAL_RANGE(reference_2.hints, result_2->hints);
RouteParameters reference_3{false, false, RouteParameters::GeometriesType::GeoJSON,
RouteParameters::OverviewType::False, true};
@@ -120,6 +124,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
CHECK_EQUAL_RANGE(reference_3.bearings, result_3->bearings);
CHECK_EQUAL_RANGE(reference_3.radiuses, result_3->radiuses);
CHECK_EQUAL_RANGE(reference_3.coordinates, result_3->coordinates);
CHECK_EQUAL_RANGE(reference_3.hints, result_3->hints);
std::vector<boost::optional<engine::Hint>> hints_4 = {
engine::Hint::FromBase64("DAIAgP___"
@@ -154,6 +159,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
CHECK_EQUAL_RANGE(reference_4.bearings, result_4->bearings);
CHECK_EQUAL_RANGE(reference_4.radiuses, result_4->radiuses);
CHECK_EQUAL_RANGE(reference_4.coordinates, result_4->coordinates);
CHECK_EQUAL_RANGE(reference_4.hints, result_4->hints);
std::vector<boost::optional<engine::Bearing>> bearings_4 = {
boost::none, engine::Bearing{200, 10}, engine::Bearing{100, 5},
@@ -177,6 +183,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
CHECK_EQUAL_RANGE(reference_5.bearings, result_5->bearings);
CHECK_EQUAL_RANGE(reference_5.radiuses, result_5->radiuses);
CHECK_EQUAL_RANGE(reference_5.coordinates, result_5->coordinates);
CHECK_EQUAL_RANGE(reference_5.hints, result_5->hints);
std::vector<util::Coordinate> coords_2 = {{util::FloatLongitude(0), util::FloatLatitude(1)},
{util::FloatLongitude(2), util::FloatLatitude(3)},
@@ -194,6 +201,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
CHECK_EQUAL_RANGE(reference_6.bearings, result_6->bearings);
CHECK_EQUAL_RANGE(reference_6.radiuses, result_6->radiuses);
CHECK_EQUAL_RANGE(reference_6.coordinates, result_6->coordinates);
CHECK_EQUAL_RANGE(reference_6.hints, result_6->hints);
auto result_7 = parseParameters<RouteParameters>("1,2;3,4?radiuses=;unlimited");
RouteParameters reference_7{};
@@ -208,6 +216,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
CHECK_EQUAL_RANGE(reference_7.bearings, result_7->bearings);
CHECK_EQUAL_RANGE(reference_7.radiuses, result_7->radiuses);
CHECK_EQUAL_RANGE(reference_7.coordinates, result_7->coordinates);
CHECK_EQUAL_RANGE(reference_7.hints, result_7->hints);
auto result_8 = parseParameters<RouteParameters>("1,2;3,4?radiuses=;");
RouteParameters reference_8{};
@@ -223,11 +232,16 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
BOOST_CHECK(result_9);
CHECK_EQUAL_RANGE(reference_9.radiuses, result_9->radiuses);
// Last Hint is empty
// Some Hint's are empty
std::vector<util::Coordinate> coords_3 = {{util::FloatLongitude(1), util::FloatLatitude(2)},
{util::FloatLongitude(3), util::FloatLatitude(4)},
{util::FloatLongitude(5), util::FloatLatitude(6)},
{util::FloatLongitude(7), util::FloatLatitude(8)}};
std::vector<boost::optional<engine::Hint>> hints_10 = {
engine::Hint::FromBase64("DAIAgP___"
"38AAAAAAAAAAAIAAAAAAAAAEAAAAOgDAAD0AwAAGwAAAOUacQBQP5sCshpxAB0_"
"mwIAAAEBl-Umfg=="),
boost::none,
engine::Hint::FromBase64("cgAAgP___"
"39jAAAADgAAACIAAABeAAAAkQAAANoDAABOAgAAGwAAAFVGcQCiRJsCR0VxAOZFmw"
"IFAAEBl-Umfg=="),
@@ -237,13 +251,13 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
RouteParameters::GeometriesType::Polyline,
RouteParameters::OverviewType::Simplified,
boost::optional<bool>{},
coords_1,
coords_3,
hints_10,
std::vector<boost::optional<double>>{},
std::vector<boost::optional<engine::Bearing>>{}};
auto result_10 = parseParameters<RouteParameters>(
"1,2;3,4?steps=false&hints="
"DAIAgP___38AAAAAAAAAAAIAAAAAAAAAEAAAAOgDAAD0AwAAGwAAAOUacQBQP5sCshpxAB0_mwIAAAEBl-Umfg==;"
"1,2;3,4;5,6;7,8?steps=false&hints="
"DAIAgP___38AAAAAAAAAAAIAAAAAAAAAEAAAAOgDAAD0AwAAGwAAAOUacQBQP5sCshpxAB0_mwIAAAEBl-Umfg==;;"
"cgAAgP___39jAAAADgAAACIAAABeAAAAkQAAANoDAABOAgAAGwAAAFVGcQCiRJsCR0VxAOZFmwIFAAEBl-Umfg==;");
BOOST_CHECK(result_10);
BOOST_CHECK_EQUAL(reference_10.steps, result_10->steps);
@@ -254,6 +268,7 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
CHECK_EQUAL_RANGE(reference_10.bearings, result_10->bearings);
CHECK_EQUAL_RANGE(reference_10.radiuses, result_10->radiuses);
CHECK_EQUAL_RANGE(reference_10.coordinates, result_10->coordinates);
CHECK_EQUAL_RANGE(reference_10.hints, result_10->hints);
}
BOOST_AUTO_TEST_CASE(valid_table_urls)
+17 -18
View File
@@ -40,7 +40,7 @@ using TestStaticRTree = StaticRTree<TestData,
false,
TEST_BRANCHING_FACTOR,
TEST_LEAF_NODE_SIZE>;
using MiniStaticRTree = StaticRTree<TestData, std::vector<Coordinate>, false, 2, 3>;
using MiniStaticRTree = StaticRTree<TestData, std::vector<Coordinate>, false, 2, 128>;
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
constexpr unsigned RANDOM_SEED = 42;
@@ -52,7 +52,7 @@ static const int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
template <typename DataT> class LinearSearchNN
{
public:
LinearSearchNN(const std::shared_ptr<std::vector<Coordinate>> &coords,
LinearSearchNN(const std::vector<Coordinate> &coords,
const std::vector<DataT> &edges)
: coords(coords), edges(edges)
{
@@ -67,9 +67,9 @@ template <typename DataT> class LinearSearchNN
const DataT &rhs) {
using web_mercator::fromWGS84;
const auto lhs_result = coordinate_calculation::projectPointOnSegment(
fromWGS84(coords->at(lhs.u)), fromWGS84(coords->at(lhs.v)), projected_input);
fromWGS84(coords[lhs.u]), fromWGS84(coords[lhs.v]), projected_input);
const auto rhs_result = coordinate_calculation::projectPointOnSegment(
fromWGS84(coords->at(rhs.u)), fromWGS84(coords->at(rhs.v)), projected_input);
fromWGS84(coords[rhs.u]), fromWGS84(coords[rhs.v]), projected_input);
const auto lhs_squared_dist = coordinate_calculation::squaredEuclideanDistance(
lhs_result.second, projected_input);
const auto rhs_squared_dist = coordinate_calculation::squaredEuclideanDistance(
@@ -85,7 +85,7 @@ template <typename DataT> class LinearSearchNN
}
private:
const std::shared_ptr<std::vector<Coordinate>> &coords;
const std::vector<Coordinate> &coords;
const std::vector<TestData> &edges;
};
@@ -105,7 +105,7 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
}
};
RandomGraphFixture() : coords(std::make_shared<std::vector<Coordinate>>())
RandomGraphFixture()
{
std::mt19937 g(RANDOM_SEED);
@@ -116,10 +116,10 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
{
int lon = lon_udist(g);
int lat = lat_udist(g);
coords->emplace_back(Coordinate(FixedLongitude(lon), FixedLatitude(lat)));
coords.emplace_back(Coordinate(FixedLongitude(lon), FixedLatitude(lat)));
}
std::uniform_int_distribution<> edge_udist(0, coords->size() - 1);
std::uniform_int_distribution<> edge_udist(0, coords.size() - 1);
std::unordered_set<std::pair<unsigned, unsigned>, TupleHash> used_edges;
@@ -138,7 +138,7 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
}
}
std::shared_ptr<std::vector<Coordinate>> coords;
std::vector<Coordinate> coords;
std::vector<TestData> edges;
};
@@ -146,12 +146,11 @@ struct GraphFixture
{
GraphFixture(const std::vector<std::pair<FloatLongitude, FloatLatitude>> &input_coords,
const std::vector<std::pair<unsigned, unsigned>> &input_edges)
: coords(std::make_shared<std::vector<Coordinate>>())
{
for (unsigned i = 0; i < input_coords.size(); i++)
{
coords->emplace_back(input_coords[i].first, input_coords[i].second);
coords.emplace_back(input_coords[i].first, input_coords[i].second);
}
for (const auto &pair : input_edges)
@@ -169,7 +168,7 @@ struct GraphFixture
}
}
std::shared_ptr<std::vector<Coordinate>> coords;
std::vector<Coordinate> coords;
std::vector<TestData> edges;
};
@@ -189,13 +188,13 @@ typedef RandomGraphFixture<10, 30> TestRandomGraphFixture_10_30;
template <typename RTreeT>
void simple_verify_rtree(RTreeT &rtree,
const std::shared_ptr<std::vector<Coordinate>> &coords,
const std::vector<Coordinate> &coords,
const std::vector<TestData> &edges)
{
for (const auto &e : edges)
{
const Coordinate &pu = coords->at(e.u);
const Coordinate &pv = coords->at(e.v);
const Coordinate &pu = coords[e.u];
const Coordinate &pv = coords[e.v];
auto result_u = rtree.Nearest(pu, 1);
auto result_v = rtree.Nearest(pv, 1);
BOOST_CHECK(result_u.size() == 1 && result_v.size() == 1);
@@ -248,7 +247,7 @@ void build_rtree(const std::string &prefix,
nodes_path = prefix + ".ramIndex";
leaves_path = prefix + ".fileIndex";
RTreeT r(fixture->edges, nodes_path, leaves_path, *fixture->coords);
RTreeT r(fixture->edges, nodes_path, leaves_path, fixture->coords);
}
template <typename RTreeT = TestStaticRTree, typename FixtureT>
@@ -261,12 +260,12 @@ void construction_test(const std::string &prefix, FixtureT *fixture)
LinearSearchNN<TestData> lsnn(fixture->coords, fixture->edges);
simple_verify_rtree(rtree, fixture->coords, fixture->edges);
sampling_verify_rtree(rtree, lsnn, *fixture->coords, 100);
sampling_verify_rtree(rtree, lsnn, fixture->coords, 100);
}
BOOST_FIXTURE_TEST_CASE(construct_tiny, TestRandomGraphFixture_10_30)
{
using TinyTestTree = StaticRTree<TestData, std::vector<Coordinate>, false, 2, 1>;
using TinyTestTree = StaticRTree<TestData, std::vector<Coordinate>, false, 2, 64>;
construction_test<TinyTestTree>("test_tiny", this);
}