Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f745b40d0 | |||
| 8789b4bee9 | |||
| 7000cfa472 | |||
| b29cbd3711 | |||
| 1454d6d7d0 | |||
| 3cf8835552 | |||
| c7293f2024 | |||
| ddc8aed25d | |||
| 5f7410057c | |||
| d55d46e64e | |||
| a83150d311 | |||
| b073bf36f3 | |||
| aaea94f776 |
@@ -1,3 +1,13 @@
|
|||||||
|
# 5.7.3
|
||||||
|
- Changes from 5.7.2:
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixes 4097: .ramIndex files was able to be truncated siliently
|
||||||
|
|
||||||
|
# 5.7.2
|
||||||
|
- Changes from 5.7.1:
|
||||||
|
- Bug fixes:
|
||||||
|
- Fixes segmentation fault caused by the fix for 3977
|
||||||
|
|
||||||
# 5.7.1
|
# 5.7.1
|
||||||
- Changes from 5.7.0:
|
- Changes from 5.7.0:
|
||||||
- Bug fixes:
|
- Bug fixes:
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ endif()
|
|||||||
project(OSRM C CXX)
|
project(OSRM C CXX)
|
||||||
set(OSRM_VERSION_MAJOR 5)
|
set(OSRM_VERSION_MAJOR 5)
|
||||||
set(OSRM_VERSION_MINOR 7)
|
set(OSRM_VERSION_MINOR 7)
|
||||||
set(OSRM_VERSION_PATCH 1)
|
set(OSRM_VERSION_PATCH 3)
|
||||||
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||||
|
|
||||||
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|||||||
@@ -794,3 +794,29 @@ Feature: Basic Roundabout
|
|||||||
| 1 | f | abcda,af,af | depart,roundabout-exit-1,arrive |
|
| 1 | f | abcda,af,af | depart,roundabout-exit-1,arrive |
|
||||||
| 1 | g | abcda,bg,bg | depart,roundabout-exit-1,arrive |
|
| 1 | g | abcda,bg,bg | depart,roundabout-exit-1,arrive |
|
||||||
| 1 | h | abcda,bh,bh | depart,roundabout-exit-1,arrive |
|
| 1 | h | abcda,bh,bh | depart,roundabout-exit-1,arrive |
|
||||||
|
|
||||||
|
Scenario: CCW and CW roundabouts with overlaps
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a d g h
|
||||||
|
|
||||||
|
b c j i
|
||||||
|
f e k l
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | junction |
|
||||||
|
| abcda | tertiary | roundabout |
|
||||||
|
| ed | tertiary | |
|
||||||
|
| af | tertiary | |
|
||||||
|
| ghijg | tertiary | roundabout |
|
||||||
|
| kg | tertiary | |
|
||||||
|
| hl | tertiary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | distance |
|
||||||
|
| e | f | ed,af,af | depart,roundabout-exit-1,arrive | 80.1m |
|
||||||
|
| f | e | af,ed,ed | depart,roundabout-exit-1,arrive | 120.1m |
|
||||||
|
| k | l | kg,hl,hl | depart,roundabout-exit-1,arrive | 80.1m |
|
||||||
|
| l | k | hl,kg,kg | depart,roundabout-exit-1,arrive | 120.1m |
|
||||||
|
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ class FileWriter
|
|||||||
|
|
||||||
template <typename T> void WriteFrom(const T &src) { WriteFrom(&src, 1); }
|
template <typename T> void WriteFrom(const T &src) { WriteFrom(&src, 1); }
|
||||||
|
|
||||||
template <typename T> void WriteOne(const T tmp) { WriteFrom(tmp); }
|
template <typename T> void WriteOne(const T &tmp) { WriteFrom(tmp); }
|
||||||
|
|
||||||
void WriteElementCount32(const std::uint32_t count) { WriteOne<std::uint32_t>(count); }
|
void WriteElementCount32(const std::uint32_t count) { WriteOne<std::uint32_t>(count); }
|
||||||
void WriteElementCount64(const std::uint64_t count) { WriteOne<std::uint64_t>(count); }
|
void WriteElementCount64(const std::uint64_t count) { WriteOne<std::uint64_t>(count); }
|
||||||
|
|||||||
@@ -34,9 +34,9 @@
|
|||||||
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
|
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
(void)cond; \
|
(void)(cond); \
|
||||||
(void)coordinate; \
|
(void)(coordinate); \
|
||||||
(void)msg; \
|
(void)(msg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")
|
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef OSRM_INDEXED_DATA_HPP
|
#ifndef OSRM_INDEXED_DATA_HPP
|
||||||
#define OSRM_INDEXED_DATA_HPP
|
#define OSRM_INDEXED_DATA_HPP
|
||||||
|
|
||||||
|
#include "storage/io.hpp"
|
||||||
|
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
#include "util/string_view.hpp"
|
#include "util/string_view.hpp"
|
||||||
|
|
||||||
@@ -9,7 +11,6 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <ostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
|||||||
/// prefix length.
|
/// prefix length.
|
||||||
/// Returns the block prefix length.
|
/// Returns the block prefix length.
|
||||||
template <typename Offset, typename OffsetIterator>
|
template <typename Offset, typename OffsetIterator>
|
||||||
Offset WriteBlockReference(std::ostream &out,
|
Offset WriteBlockReference(storage::io::FileWriter &out,
|
||||||
Offset data_offset,
|
Offset data_offset,
|
||||||
OffsetIterator first,
|
OffsetIterator first,
|
||||||
OffsetIterator last) const
|
OffsetIterator last) const
|
||||||
@@ -105,7 +106,7 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
|||||||
prefix_length += byte_length;
|
prefix_length += byte_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.write((const char *)&refernce, sizeof(refernce));
|
out.WriteOne(refernce);
|
||||||
|
|
||||||
return prefix_length;
|
return prefix_length;
|
||||||
}
|
}
|
||||||
@@ -118,7 +119,8 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
|||||||
/// [first..last] is an inclusive range of block data.
|
/// [first..last] is an inclusive range of block data.
|
||||||
/// The length of the last item in the block is not stored.
|
/// The length of the last item in the block is not stored.
|
||||||
template <typename OffsetIterator>
|
template <typename OffsetIterator>
|
||||||
void WriteBlockPrefix(std::ostream &out, OffsetIterator first, OffsetIterator last) const
|
void
|
||||||
|
WriteBlockPrefix(storage::io::FileWriter &out, OffsetIterator first, OffsetIterator last) const
|
||||||
{
|
{
|
||||||
for (OffsetIterator curr = first, next = std::next(first); curr != last; ++curr, ++next)
|
for (OffsetIterator curr = first, next = std::next(first); curr != last; ++curr, ++next)
|
||||||
{
|
{
|
||||||
@@ -127,7 +129,9 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
|||||||
if (byte_length == 0)
|
if (byte_length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
out.write((const char *)&data_length, byte_length);
|
// Here, we're only writing a few bytes from the 4-byte std::uint32_t,
|
||||||
|
// so we need to cast to (char *)
|
||||||
|
out.WriteFrom((const char *)&data_length, byte_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,20 +179,23 @@ template <int N, typename T = std::string> struct FixedGroupBlock
|
|||||||
/// Write a block reference {offset}, where offset is a global block offset
|
/// Write a block reference {offset}, where offset is a global block offset
|
||||||
/// Returns the fixed block prefix length.
|
/// Returns the fixed block prefix length.
|
||||||
template <typename Offset, typename OffsetIterator>
|
template <typename Offset, typename OffsetIterator>
|
||||||
Offset
|
Offset WriteBlockReference(storage::io::FileWriter &out,
|
||||||
WriteBlockReference(std::ostream &out, Offset data_offset, OffsetIterator, OffsetIterator) const
|
Offset data_offset,
|
||||||
|
OffsetIterator,
|
||||||
|
OffsetIterator) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(data_offset <= std::numeric_limits<decltype(BlockReference::offset)>::max());
|
BOOST_ASSERT(data_offset <= std::numeric_limits<decltype(BlockReference::offset)>::max());
|
||||||
|
|
||||||
BlockReference refernce{static_cast<decltype(BlockReference::offset)>(data_offset)};
|
BlockReference refernce{static_cast<decltype(BlockReference::offset)>(data_offset)};
|
||||||
out.write((const char *)&refernce, sizeof(refernce));
|
out.WriteOne(refernce);
|
||||||
|
|
||||||
return BLOCK_SIZE;
|
return BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a fixed length block prefix.
|
/// Write a fixed length block prefix.
|
||||||
template <typename OffsetIterator>
|
template <typename OffsetIterator>
|
||||||
void WriteBlockPrefix(std::ostream &out, OffsetIterator first, OffsetIterator last) const
|
void
|
||||||
|
WriteBlockPrefix(storage::io::FileWriter &out, OffsetIterator first, OffsetIterator last) const
|
||||||
{
|
{
|
||||||
std::uint32_t index = 0;
|
std::uint32_t index = 0;
|
||||||
std::array<ValueType, BLOCK_SIZE> block_prefix;
|
std::array<ValueType, BLOCK_SIZE> block_prefix;
|
||||||
@@ -200,7 +207,7 @@ template <int N, typename T = std::string> struct FixedGroupBlock
|
|||||||
|
|
||||||
block_prefix[index++] = static_cast<ValueType>(data_length);
|
block_prefix[index++] = static_cast<ValueType>(data_length);
|
||||||
}
|
}
|
||||||
out.write((const char *)block_prefix.data(), block_prefix.size());
|
out.WriteFrom(block_prefix.data(), block_prefix.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Advances the range to an item stored in the referenced block.
|
/// Advances the range to an item stored in the referenced block.
|
||||||
@@ -244,8 +251,10 @@ template <typename GroupBlock> struct IndexedData
|
|||||||
bool empty() const { return blocks_number == 0; }
|
bool empty() const { return blocks_number == 0; }
|
||||||
|
|
||||||
template <typename OffsetIterator, typename DataIterator>
|
template <typename OffsetIterator, typename DataIterator>
|
||||||
void
|
void write(storage::io::FileWriter &out,
|
||||||
write(std::ostream &out, OffsetIterator first, OffsetIterator last, DataIterator data) const
|
OffsetIterator first,
|
||||||
|
OffsetIterator last,
|
||||||
|
DataIterator data) const
|
||||||
{
|
{
|
||||||
static_assert(sizeof(typename DataIterator::value_type) == 1, "data basic type must char");
|
static_assert(sizeof(typename DataIterator::value_type) == 1, "data basic type must char");
|
||||||
|
|
||||||
@@ -259,7 +268,7 @@ template <typename GroupBlock> struct IndexedData
|
|||||||
const BlocksNumberType number_of_blocks =
|
const BlocksNumberType number_of_blocks =
|
||||||
number_of_elements == 0 ? 0
|
number_of_elements == 0 ? 0
|
||||||
: 1 + (std::distance(first, sentinel) - 1) / (BLOCK_SIZE + 1);
|
: 1 + (std::distance(first, sentinel) - 1) / (BLOCK_SIZE + 1);
|
||||||
out.write((const char *)&number_of_blocks, sizeof(number_of_blocks));
|
out.WriteOne(number_of_blocks);
|
||||||
|
|
||||||
// Write block references and compute the total data size that includes prefix and data
|
// Write block references and compute the total data size that includes prefix and data
|
||||||
const GroupBlock block;
|
const GroupBlock block;
|
||||||
@@ -273,7 +282,7 @@ template <typename GroupBlock> struct IndexedData
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the total data size
|
// Write the total data size
|
||||||
out.write((const char *)&data_size, sizeof(data_size));
|
out.WriteOne(data_size);
|
||||||
|
|
||||||
// Write data blocks that are (prefix, data)
|
// Write data blocks that are (prefix, data)
|
||||||
for (OffsetIterator curr = first, next = first; next != sentinel; curr = next)
|
for (OffsetIterator curr = first, next = first; next != sentinel; curr = next)
|
||||||
@@ -281,7 +290,8 @@ template <typename GroupBlock> struct IndexedData
|
|||||||
std::advance(next, std::min<diff_type>(BLOCK_SIZE, std::distance(next, sentinel)));
|
std::advance(next, std::min<diff_type>(BLOCK_SIZE, std::distance(next, sentinel)));
|
||||||
block.WriteBlockPrefix(out, curr, next);
|
block.WriteBlockPrefix(out, curr, next);
|
||||||
std::advance(next, std::min<diff_type>(1, std::distance(next, sentinel)));
|
std::advance(next, std::min<diff_type>(1, std::distance(next, sentinel)));
|
||||||
std::copy(data + *curr, data + *next, std::ostream_iterator<unsigned char>(out));
|
std::for_each(
|
||||||
|
data + *curr, data + *next, [&out](const auto &element) { out.WriteOne(element); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/iostreams/device/mapped_file.hpp>
|
#include <boost/iostreams/device/mapped_file.hpp>
|
||||||
|
|
||||||
@@ -204,73 +203,78 @@ class StaticRTree
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// open leaf file
|
std::vector<TreeNode> tree_nodes_in_level;
|
||||||
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
|
|
||||||
|
|
||||||
// sort the hilbert-value representatives
|
// sort the hilbert-value representatives
|
||||||
tbb::parallel_sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
|
tbb::parallel_sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
|
||||||
std::vector<TreeNode> tree_nodes_in_level;
|
|
||||||
|
|
||||||
// pack M elements into leaf node, write to leaf file and add child index to the parent node
|
|
||||||
uint64_t wrapped_element_index = 0;
|
|
||||||
for (std::uint32_t node_index = 0; wrapped_element_index < element_count; ++node_index)
|
|
||||||
{
|
{
|
||||||
TreeNode current_node;
|
storage::io::FileWriter leaf_node_file(leaf_node_filename,
|
||||||
for (std::uint32_t leaf_index = 0;
|
storage::io::FileWriter::HasNoFingerprint);
|
||||||
leaf_index < BRANCHING_FACTOR && wrapped_element_index < element_count;
|
|
||||||
++leaf_index)
|
// pack M elements into leaf node, write to leaf file and add child index to the parent
|
||||||
|
// node
|
||||||
|
uint64_t wrapped_element_index = 0;
|
||||||
|
for (std::uint32_t node_index = 0; wrapped_element_index < element_count; ++node_index)
|
||||||
{
|
{
|
||||||
LeafNode current_leaf;
|
TreeNode current_node;
|
||||||
Rectangle &rectangle = current_leaf.minimum_bounding_rectangle;
|
for (std::uint32_t leaf_index = 0;
|
||||||
for (std::uint32_t object_index = 0;
|
leaf_index < BRANCHING_FACTOR && wrapped_element_index < element_count;
|
||||||
object_index < LEAF_NODE_SIZE && wrapped_element_index < element_count;
|
++leaf_index)
|
||||||
++object_index, ++wrapped_element_index)
|
|
||||||
{
|
{
|
||||||
const std::uint32_t input_object_index =
|
LeafNode current_leaf;
|
||||||
input_wrapper_vector[wrapped_element_index].m_array_index;
|
Rectangle &rectangle = current_leaf.minimum_bounding_rectangle;
|
||||||
const EdgeDataT &object = input_data_vector[input_object_index];
|
for (std::uint32_t object_index = 0;
|
||||||
|
object_index < LEAF_NODE_SIZE && wrapped_element_index < element_count;
|
||||||
|
++object_index, ++wrapped_element_index)
|
||||||
|
{
|
||||||
|
const std::uint32_t input_object_index =
|
||||||
|
input_wrapper_vector[wrapped_element_index].m_array_index;
|
||||||
|
const EdgeDataT &object = input_data_vector[input_object_index];
|
||||||
|
|
||||||
current_leaf.object_count += 1;
|
current_leaf.object_count += 1;
|
||||||
current_leaf.objects[object_index] = object;
|
current_leaf.objects[object_index] = object;
|
||||||
|
|
||||||
Coordinate projected_u{
|
Coordinate projected_u{
|
||||||
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.u]})};
|
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.u]})};
|
||||||
Coordinate projected_v{
|
Coordinate projected_v{
|
||||||
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.v]})};
|
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.v]})};
|
||||||
|
|
||||||
BOOST_ASSERT(std::abs(toFloating(projected_u.lon).operator double()) <= 180.);
|
BOOST_ASSERT(std::abs(toFloating(projected_u.lon).operator double()) <=
|
||||||
BOOST_ASSERT(std::abs(toFloating(projected_u.lat).operator double()) <= 180.);
|
180.);
|
||||||
BOOST_ASSERT(std::abs(toFloating(projected_v.lon).operator double()) <= 180.);
|
BOOST_ASSERT(std::abs(toFloating(projected_u.lat).operator double()) <=
|
||||||
BOOST_ASSERT(std::abs(toFloating(projected_v.lat).operator double()) <= 180.);
|
180.);
|
||||||
|
BOOST_ASSERT(std::abs(toFloating(projected_v.lon).operator double()) <=
|
||||||
|
180.);
|
||||||
|
BOOST_ASSERT(std::abs(toFloating(projected_v.lat).operator double()) <=
|
||||||
|
180.);
|
||||||
|
|
||||||
rectangle.min_lon =
|
rectangle.min_lon =
|
||||||
std::min(rectangle.min_lon, std::min(projected_u.lon, projected_v.lon));
|
std::min(rectangle.min_lon, std::min(projected_u.lon, projected_v.lon));
|
||||||
rectangle.max_lon =
|
rectangle.max_lon =
|
||||||
std::max(rectangle.max_lon, std::max(projected_u.lon, projected_v.lon));
|
std::max(rectangle.max_lon, std::max(projected_u.lon, projected_v.lon));
|
||||||
|
|
||||||
rectangle.min_lat =
|
rectangle.min_lat =
|
||||||
std::min(rectangle.min_lat, std::min(projected_u.lat, projected_v.lat));
|
std::min(rectangle.min_lat, std::min(projected_u.lat, projected_v.lat));
|
||||||
rectangle.max_lat =
|
rectangle.max_lat =
|
||||||
std::max(rectangle.max_lat, std::max(projected_u.lat, projected_v.lat));
|
std::max(rectangle.max_lat, std::max(projected_u.lat, projected_v.lat));
|
||||||
|
|
||||||
BOOST_ASSERT(rectangle.IsValid());
|
BOOST_ASSERT(rectangle.IsValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
// append the leaf node to the current tree node
|
||||||
|
current_node.child_count += 1;
|
||||||
|
current_node.children[leaf_index] =
|
||||||
|
TreeIndex{node_index * BRANCHING_FACTOR + leaf_index, true};
|
||||||
|
current_node.minimum_bounding_rectangle.MergeBoundingBoxes(
|
||||||
|
current_leaf.minimum_bounding_rectangle);
|
||||||
|
|
||||||
|
// write leaf_node to leaf node file
|
||||||
|
leaf_node_file.WriteOne(current_leaf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// append the leaf node to the current tree node
|
tree_nodes_in_level.emplace_back(current_node);
|
||||||
current_node.child_count += 1;
|
|
||||||
current_node.children[leaf_index] =
|
|
||||||
TreeIndex{node_index * BRANCHING_FACTOR + leaf_index, true};
|
|
||||||
current_node.minimum_bounding_rectangle.MergeBoundingBoxes(
|
|
||||||
current_leaf.minimum_bounding_rectangle);
|
|
||||||
|
|
||||||
// write leaf_node to leaf node file
|
|
||||||
leaf_node_file.write((char *)¤t_leaf, sizeof(current_leaf));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_nodes_in_level.emplace_back(current_node);
|
|
||||||
}
|
}
|
||||||
leaf_node_file.flush();
|
|
||||||
leaf_node_file.close();
|
|
||||||
|
|
||||||
std::uint32_t processing_level = 0;
|
std::uint32_t processing_level = 0;
|
||||||
while (1 < tree_nodes_in_level.size())
|
while (1 < tree_nodes_in_level.size())
|
||||||
@@ -332,15 +336,17 @@ class StaticRTree
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// open tree file
|
{
|
||||||
storage::io::FileWriter tree_node_file(tree_node_filename,
|
// open tree file
|
||||||
storage::io::FileWriter::HasNoFingerprint);
|
storage::io::FileWriter tree_node_file(tree_node_filename,
|
||||||
|
storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
|
||||||
std::uint64_t size_of_tree = m_search_tree.size();
|
std::uint64_t size_of_tree = m_search_tree.size();
|
||||||
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
||||||
|
|
||||||
tree_node_file.WriteOne(size_of_tree);
|
tree_node_file.WriteOne(size_of_tree);
|
||||||
tree_node_file.WriteFrom(&m_search_tree[0], size_of_tree);
|
tree_node_file.WriteFrom(&m_search_tree[0], size_of_tree);
|
||||||
|
}
|
||||||
|
|
||||||
MapLeafNodesFile(leaf_node_filename);
|
MapLeafNodesFile(leaf_node_filename);
|
||||||
}
|
}
|
||||||
@@ -379,6 +385,24 @@ class StaticRTree
|
|||||||
std::size_t num_leaves = m_leaves_region.size() / sizeof(LeafNode);
|
std::size_t num_leaves = m_leaves_region.size() / sizeof(LeafNode);
|
||||||
auto data_ptr = m_leaves_region.data();
|
auto data_ptr = m_leaves_region.data();
|
||||||
BOOST_ASSERT(reinterpret_cast<uintptr_t>(data_ptr) % alignof(LeafNode) == 0);
|
BOOST_ASSERT(reinterpret_cast<uintptr_t>(data_ptr) % alignof(LeafNode) == 0);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Find the maximum leaf node ID and make sure we have that many from our file
|
||||||
|
BOOST_ASSERT(m_search_tree.size() > 0);
|
||||||
|
std::uint32_t max_leaf_node_id = 0;
|
||||||
|
// Search in reverse, the bottom of the tree is at the end of the array
|
||||||
|
for (auto iter = m_search_tree.rbegin(); iter != m_search_tree.rend(); iter++)
|
||||||
|
{
|
||||||
|
// If we find a non-leaf node, we can quit, we've seen the
|
||||||
|
// bottom level of the tree
|
||||||
|
if (iter->child_count > 0 && !iter->children[0].is_leaf)
|
||||||
|
break;
|
||||||
|
for (std::uint32_t i = 0; i < iter->child_count; ++i)
|
||||||
|
{
|
||||||
|
max_leaf_node_id = std::max(max_leaf_node_id, iter->children[i].index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(max_leaf_node_id == num_leaves - 1);
|
||||||
|
#endif
|
||||||
m_leaves.reset(reinterpret_cast<const LeafNode *>(data_ptr), num_leaves);
|
m_leaves.reset(reinterpret_cast<const LeafNode *>(data_ptr), num_leaves);
|
||||||
}
|
}
|
||||||
catch (const std::exception &exc)
|
catch (const std::exception &exc)
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrm",
|
"name": "osrm",
|
||||||
"version": "5.7.1",
|
"version": "5.7.3",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ void ExtractionContainers::WriteCharData(const std::string &file_name)
|
|||||||
util::UnbufferedLog log;
|
util::UnbufferedLog log;
|
||||||
log << "writing street name index ... ";
|
log << "writing street name index ... ";
|
||||||
TIMER_START(write_index);
|
TIMER_START(write_index);
|
||||||
boost::filesystem::ofstream file(file_name, std::ios::binary);
|
storage::io::FileWriter file(file_name, storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
|
||||||
const util::NameTable::IndexedData indexed_data;
|
const util::NameTable::IndexedData indexed_data;
|
||||||
indexed_data.write(file, name_offsets.begin(), name_offsets.end(), name_char_data.begin());
|
indexed_data.write(file, name_offsets.begin(), name_offsets.end(), name_char_data.begin());
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "extractor/geojson_debug_policies.hpp"
|
#include "extractor/geojson_debug_policies.hpp"
|
||||||
#include "util/geojson_debug_logger.hpp"
|
#include "util/geojson_debug_logger.hpp"
|
||||||
|
|
||||||
|
#include "util/assert.hpp"
|
||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/log.hpp"
|
#include "util/log.hpp"
|
||||||
@@ -278,7 +279,8 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// due to merging of roads, the u-turn might actually not be part of the intersection anymore
|
// due to merging of roads, the u-turn might actually not be part of the intersection anymore
|
||||||
const auto uturn_bearing = [&]() {
|
// uturn is a pair of {edge id, bearing}
|
||||||
|
const auto uturn = [&]() {
|
||||||
const auto merge_entry = std::find_if(
|
const auto merge_entry = std::find_if(
|
||||||
performed_merges.begin(), performed_merges.end(), [&uturn_edge_itr](const auto entry) {
|
performed_merges.begin(), performed_merges.end(), [&uturn_edge_itr](const auto entry) {
|
||||||
return entry.merged_eid == uturn_edge_itr->eid;
|
return entry.merged_eid == uturn_edge_itr->eid;
|
||||||
@@ -291,7 +293,8 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
normalized_intersection.end(),
|
normalized_intersection.end(),
|
||||||
[&](const IntersectionShapeData &road) { return road.eid == merged_into_id; });
|
[&](const IntersectionShapeData &road) { return road.eid == merged_into_id; });
|
||||||
BOOST_ASSERT(merged_u_turn != normalized_intersection.end());
|
BOOST_ASSERT(merged_u_turn != normalized_intersection.end());
|
||||||
return util::bearing::reverse(merged_u_turn->bearing);
|
return std::make_pair(merged_u_turn->eid,
|
||||||
|
util::bearing::reverse(merged_u_turn->bearing));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -301,7 +304,9 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
connect_to_previous_node);
|
connect_to_previous_node);
|
||||||
BOOST_ASSERT(uturn_edge_at_normalized_intersection_itr !=
|
BOOST_ASSERT(uturn_edge_at_normalized_intersection_itr !=
|
||||||
normalized_intersection.end());
|
normalized_intersection.end());
|
||||||
return util::bearing::reverse(uturn_edge_at_normalized_intersection_itr->bearing);
|
return std::make_pair(
|
||||||
|
uturn_edge_at_normalized_intersection_itr->eid,
|
||||||
|
util::bearing::reverse(uturn_edge_at_normalized_intersection_itr->bearing));
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
@@ -314,7 +319,7 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
return IntersectionViewData(
|
return IntersectionViewData(
|
||||||
road,
|
road,
|
||||||
is_allowed_turn(road),
|
is_allowed_turn(road),
|
||||||
util::bearing::angleBetween(uturn_bearing, road.bearing));
|
util::bearing::angleBetween(uturn.second, road.bearing));
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto uturn_edge_at_intersection_view_itr =
|
const auto uturn_edge_at_intersection_view_itr =
|
||||||
@@ -369,8 +374,22 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
|||||||
std::end(intersection_view),
|
std::end(intersection_view),
|
||||||
std::mem_fn(&IntersectionViewData::CompareByAngle));
|
std::mem_fn(&IntersectionViewData::CompareByAngle));
|
||||||
|
|
||||||
BOOST_ASSERT(intersection_view[0].angle >= 0. &&
|
// Move entering_via_edge to intersection front and place all roads prior entering_via_edge
|
||||||
intersection_view[0].angle < std::numeric_limits<double>::epsilon());
|
// at the end of the intersection view with 360° angle
|
||||||
|
auto entering_via_it = std::find_if(intersection_view.begin(),
|
||||||
|
intersection_view.end(),
|
||||||
|
[&uturn](auto &road) { return road.eid == uturn.first; });
|
||||||
|
|
||||||
|
OSRM_ASSERT(entering_via_it != intersection_view.end() && entering_via_it->angle >= 0. &&
|
||||||
|
entering_via_it->angle < std::numeric_limits<double>::epsilon(),
|
||||||
|
coordinates[node_at_intersection]);
|
||||||
|
|
||||||
|
if (entering_via_it != intersection_view.begin() && entering_via_it != intersection_view.end())
|
||||||
|
{
|
||||||
|
std::for_each(
|
||||||
|
intersection_view.begin(), entering_via_it, [](auto &road) { road.angle = 360.; });
|
||||||
|
std::rotate(intersection_view.begin(), entering_via_it, intersection_view.end());
|
||||||
|
}
|
||||||
|
|
||||||
return intersection_view;
|
return intersection_view;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "extractor/guidance/roundabout_handler.hpp"
|
#include "extractor/guidance/roundabout_handler.hpp"
|
||||||
#include "extractor/guidance/constants.hpp"
|
#include "extractor/guidance/constants.hpp"
|
||||||
|
|
||||||
|
#include "util/assert.hpp"
|
||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/guidance/name_announcements.hpp"
|
#include "util/guidance/name_announcements.hpp"
|
||||||
@@ -158,6 +159,8 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OSRM_ASSERT(invalidate_from <= invalidate_to, coordinates[from_nid]);
|
||||||
|
|
||||||
// Exiting roundabouts at an entry point is technically a data-modelling issue.
|
// Exiting roundabouts at an entry point is technically a data-modelling issue.
|
||||||
// This workaround handles cases in which an exit precedes and entry. The resulting
|
// This workaround handles cases in which an exit precedes and entry. The resulting
|
||||||
// u-turn against the roundabout direction is invalidated.
|
// u-turn against the roundabout direction is invalidated.
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "util/indexed_data.hpp"
|
#include "util/indexed_data.hpp"
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
#include <boost/test/test_case_template.hpp>
|
#include <boost/test/test_case_template.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
@@ -34,11 +36,18 @@ BOOST_AUTO_TEST_CASE(check_variable_group_block_bitops)
|
|||||||
template <typename IndexedData, typename Offsets, typename Data>
|
template <typename IndexedData, typename Offsets, typename Data>
|
||||||
void test_rw(const Offsets &offsets, const Data &data)
|
void test_rw(const Offsets &offsets, const Data &data)
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
|
||||||
IndexedData indexed_data;
|
IndexedData indexed_data;
|
||||||
indexed_data.write(sstr, offsets.begin(), offsets.end(), data.begin());
|
auto path = boost::filesystem::unique_path();
|
||||||
|
|
||||||
const std::string str = sstr.str();
|
{
|
||||||
|
storage::io::FileWriter writer(path, storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
indexed_data.write(writer, offsets.begin(), offsets.end(), data.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
storage::io::FileReader reader(path, storage::io::FileReader::HasNoFingerprint);
|
||||||
|
auto length = reader.GetSize();
|
||||||
|
std::string str(length, '\0');
|
||||||
|
reader.ReadInto(const_cast<char *>(str.data()), length);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
std::cout << "\n" << typeid(IndexedData).name() << "\nsaved size = " << str.size() << "\n";
|
std::cout << "\n" << typeid(IndexedData).name() << "\nsaved size = " << str.size() << "\n";
|
||||||
@@ -175,14 +184,21 @@ BOOST_AUTO_TEST_CASE(check_corrupted_memory)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(check_string_view)
|
BOOST_AUTO_TEST_CASE(check_string_view)
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
auto path = boost::filesystem::unique_path();
|
||||||
std::string name_data = "hellostringview";
|
std::string name_data = "hellostringview";
|
||||||
std::vector<std::uint32_t> name_offsets = {0, 5, 11, 15};
|
std::vector<std::uint32_t> name_offsets = {0, 5, 11, 15};
|
||||||
|
|
||||||
IndexedData<VariableGroupBlock<16, StringView>> indexed_data;
|
IndexedData<VariableGroupBlock<16, StringView>> indexed_data;
|
||||||
indexed_data.write(sstr, name_offsets.begin(), name_offsets.end(), name_data.begin());
|
{
|
||||||
|
storage::io::FileWriter writer(path, storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
indexed_data.write(writer, name_offsets.begin(), name_offsets.end(), name_data.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
storage::io::FileReader reader(path, storage::io::FileReader::HasNoFingerprint);
|
||||||
|
auto length = reader.GetSize();
|
||||||
|
std::string str(length, '\0');
|
||||||
|
reader.ReadInto(const_cast<char *>(str.data()), length);
|
||||||
|
|
||||||
const std::string str = sstr.str();
|
|
||||||
indexed_data.reset(str.c_str(), str.c_str() + str.size());
|
indexed_data.reset(str.c_str(), str.c_str() + str.size());
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(indexed_data.at(0), "hello");
|
BOOST_CHECK_EQUAL(indexed_data.at(0), "hello");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "util/name_table.hpp"
|
#include "util/name_table.hpp"
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/test/test_case_template.hpp>
|
#include <boost/test/test_case_template.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
@@ -19,7 +20,6 @@ using namespace osrm::util;
|
|||||||
|
|
||||||
std::string PrapareNameTableData(std::vector<std::string> &data, bool fill_all)
|
std::string PrapareNameTableData(std::vector<std::string> &data, bool fill_all)
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
|
||||||
NameTable::IndexedData indexed_data;
|
NameTable::IndexedData indexed_data;
|
||||||
std::vector<unsigned char> name_char_data;
|
std::vector<unsigned char> name_char_data;
|
||||||
std::vector<std::uint32_t> name_offsets;
|
std::vector<std::uint32_t> name_offsets;
|
||||||
@@ -54,9 +54,19 @@ std::string PrapareNameTableData(std::vector<std::string> &data, bool fill_all)
|
|||||||
}
|
}
|
||||||
name_offsets.push_back(name_char_data.size());
|
name_offsets.push_back(name_char_data.size());
|
||||||
|
|
||||||
indexed_data.write(sstr, name_offsets.begin(), name_offsets.end(), name_char_data.begin());
|
auto path = boost::filesystem::unique_path();
|
||||||
|
{
|
||||||
|
storage::io::FileWriter writer(path, storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
indexed_data.write(
|
||||||
|
writer, name_offsets.begin(), name_offsets.end(), name_char_data.begin());
|
||||||
|
}
|
||||||
|
|
||||||
return sstr.str();
|
storage::io::FileReader reader(path, storage::io::FileReader::HasNoFingerprint);
|
||||||
|
auto length = reader.GetSize();
|
||||||
|
std::string str(length, '\0');
|
||||||
|
reader.ReadInto(const_cast<char *>(str.data()), length);
|
||||||
|
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(check_name_table_fill)
|
BOOST_AUTO_TEST_CASE(check_name_table_fill)
|
||||||
|
|||||||
Reference in New Issue
Block a user