Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0333809da8 | |||
| ceb0e31659 | |||
| cc6923bfa9 | |||
| 1b2f1a459d | |||
| f3b4440707 | |||
| 6f745b40d0 | |||
| 8789b4bee9 | |||
| 7000cfa472 | |||
| b29cbd3711 | |||
| 1454d6d7d0 | |||
| 3cf8835552 | |||
| c7293f2024 | |||
| ddc8aed25d | |||
| 5f7410057c | |||
| d55d46e64e | |||
| a83150d311 | |||
| b073bf36f3 | |||
| aaea94f776 |
@@ -1,3 +1,19 @@
|
||||
# 5.7.4
|
||||
- Changes from 5.7.3:
|
||||
- Bug fixes:
|
||||
- Fixes 4100: Fix steps collapsing after non-closed roundabouts
|
||||
- Fixes 4129: Fix invalid roundabout instructions for different driving modes
|
||||
|
||||
# 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
|
||||
- Changes from 5.7.0:
|
||||
- Bug fixes:
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ endif()
|
||||
project(OSRM C CXX)
|
||||
set(OSRM_VERSION_MAJOR 5)
|
||||
set(OSRM_VERSION_MINOR 7)
|
||||
set(OSRM_VERSION_PATCH 1)
|
||||
set(OSRM_VERSION_PATCH 4)
|
||||
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||
|
||||
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
@@ -37,3 +37,37 @@ Feature: Basic Roundabout
|
||||
| h,a | gh,ab,ab | depart,roundabout turn left exit-3,arrive |
|
||||
| h,d | gh,cd,cd | depart,roundabout turn straight exit-2,arrive |
|
||||
| h,f | gh,ef,ef | depart,roundabout turn right exit-1,arrive |
|
||||
|
||||
# https://www.openstreetmap.org/way/223225602
|
||||
Scenario: Enter and Exit with changing mode
|
||||
Given the node map
|
||||
"""
|
||||
a
|
||||
b
|
||||
h g c d
|
||||
e
|
||||
f
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | junction | highway |
|
||||
| ab | | residential |
|
||||
| cd | | residential |
|
||||
| ef | | footway |
|
||||
| gh | | footway |
|
||||
| bgecb | roundabout | residential |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
|
||||
| a,f | ab,ef,ef,ef | depart,roundabout turn left exit-1,notification right,arrive |
|
||||
| a,h | ab,bgecb,gh,gh | depart,roundabout turn right exit-1,notification right,arrive |
|
||||
| d,f | cd,ef,ef,ef | depart,roundabout turn sharp left exit-2,notification right,arrive |
|
||||
| d,h | cd,gh,gh,gh | depart,roundabout turn left exit-2,notification right,arrive |
|
||||
| d,a | cd,ab,ab | depart,roundabout turn right exit-1,arrive |
|
||||
| f,h | ef,gh,gh,gh | depart,roundabout turn sharp left exit-3,notification right,arrive |
|
||||
| f,a | ef,ab,ab | depart,roundabout turn straight exit-2,arrive |
|
||||
| f,d | ef,cd,cd | depart,roundabout turn right exit-1,arrive |
|
||||
| h,a | gh,ab,ab | depart,roundabout turn left exit-2,arrive |
|
||||
| h,d | gh,cd,cd | depart,roundabout turn straight exit-1,arrive |
|
||||
| h,f | gh,bgecb,ef,ef | depart,roundabout turn right exit-1,notification right,arrive |
|
||||
|
||||
@@ -794,3 +794,29 @@ Feature: Basic Roundabout
|
||||
| 1 | f | abcda,af,af | 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 |
|
||||
|
||||
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 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 WriteElementCount64(const std::uint64_t count) { WriteOne<std::uint64_t>(count); }
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
#define OSRM_ASSERT_MSG(cond, coordinate, msg) \
|
||||
do \
|
||||
{ \
|
||||
(void)cond; \
|
||||
(void)coordinate; \
|
||||
(void)msg; \
|
||||
(void)(cond); \
|
||||
(void)(coordinate); \
|
||||
(void)(msg); \
|
||||
} while (0)
|
||||
#define OSRM_ASSERT(cond, coordinate) OSRM_ASSERT_MSG(cond, coordinate, "")
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef OSRM_INDEXED_DATA_HPP
|
||||
#define OSRM_INDEXED_DATA_HPP
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
#include "util/exception.hpp"
|
||||
#include "util/string_view.hpp"
|
||||
|
||||
@@ -9,7 +11,6 @@
|
||||
#include <array>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
@@ -85,7 +86,7 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
||||
/// prefix length.
|
||||
/// Returns the block prefix length.
|
||||
template <typename Offset, typename OffsetIterator>
|
||||
Offset WriteBlockReference(std::ostream &out,
|
||||
Offset WriteBlockReference(storage::io::FileWriter &out,
|
||||
Offset data_offset,
|
||||
OffsetIterator first,
|
||||
OffsetIterator last) const
|
||||
@@ -105,7 +106,7 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
||||
prefix_length += byte_length;
|
||||
}
|
||||
|
||||
out.write((const char *)&refernce, sizeof(refernce));
|
||||
out.WriteOne(refernce);
|
||||
|
||||
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.
|
||||
/// The length of the last item in the block is not stored.
|
||||
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)
|
||||
{
|
||||
@@ -127,7 +129,9 @@ template <int N, typename T = std::string> struct VariableGroupBlock
|
||||
if (byte_length == 0)
|
||||
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
|
||||
/// Returns the fixed block prefix length.
|
||||
template <typename Offset, typename OffsetIterator>
|
||||
Offset
|
||||
WriteBlockReference(std::ostream &out, Offset data_offset, OffsetIterator, OffsetIterator) const
|
||||
Offset WriteBlockReference(storage::io::FileWriter &out,
|
||||
Offset data_offset,
|
||||
OffsetIterator,
|
||||
OffsetIterator) const
|
||||
{
|
||||
BOOST_ASSERT(data_offset <= std::numeric_limits<decltype(BlockReference::offset)>::max());
|
||||
|
||||
BlockReference refernce{static_cast<decltype(BlockReference::offset)>(data_offset)};
|
||||
out.write((const char *)&refernce, sizeof(refernce));
|
||||
out.WriteOne(refernce);
|
||||
|
||||
return BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/// Write a fixed length block prefix.
|
||||
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::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);
|
||||
}
|
||||
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.
|
||||
@@ -244,8 +251,10 @@ template <typename GroupBlock> struct IndexedData
|
||||
bool empty() const { return blocks_number == 0; }
|
||||
|
||||
template <typename OffsetIterator, typename DataIterator>
|
||||
void
|
||||
write(std::ostream &out, OffsetIterator first, OffsetIterator last, DataIterator data) const
|
||||
void write(storage::io::FileWriter &out,
|
||||
OffsetIterator first,
|
||||
OffsetIterator last,
|
||||
DataIterator data) const
|
||||
{
|
||||
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 =
|
||||
number_of_elements == 0 ? 0
|
||||
: 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
|
||||
const GroupBlock block;
|
||||
@@ -273,7 +282,7 @@ template <typename GroupBlock> struct IndexedData
|
||||
}
|
||||
|
||||
// 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)
|
||||
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)));
|
||||
block.WriteBlockPrefix(out, curr, next);
|
||||
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/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/iostreams/device/mapped_file.hpp>
|
||||
|
||||
@@ -204,73 +203,78 @@ class StaticRTree
|
||||
}
|
||||
});
|
||||
|
||||
// open leaf file
|
||||
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
|
||||
|
||||
std::vector<TreeNode> tree_nodes_in_level;
|
||||
// sort the hilbert-value representatives
|
||||
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;
|
||||
for (std::uint32_t leaf_index = 0;
|
||||
leaf_index < BRANCHING_FACTOR && wrapped_element_index < element_count;
|
||||
++leaf_index)
|
||||
storage::io::FileWriter leaf_node_file(leaf_node_filename,
|
||||
storage::io::FileWriter::HasNoFingerprint);
|
||||
|
||||
// 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;
|
||||
Rectangle &rectangle = current_leaf.minimum_bounding_rectangle;
|
||||
for (std::uint32_t object_index = 0;
|
||||
object_index < LEAF_NODE_SIZE && wrapped_element_index < element_count;
|
||||
++object_index, ++wrapped_element_index)
|
||||
TreeNode current_node;
|
||||
for (std::uint32_t leaf_index = 0;
|
||||
leaf_index < BRANCHING_FACTOR && wrapped_element_index < element_count;
|
||||
++leaf_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];
|
||||
LeafNode current_leaf;
|
||||
Rectangle &rectangle = current_leaf.minimum_bounding_rectangle;
|
||||
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.objects[object_index] = object;
|
||||
current_leaf.object_count += 1;
|
||||
current_leaf.objects[object_index] = object;
|
||||
|
||||
Coordinate projected_u{
|
||||
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.u]})};
|
||||
Coordinate projected_v{
|
||||
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.v]})};
|
||||
Coordinate projected_u{
|
||||
web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.u]})};
|
||||
Coordinate projected_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.lat).operator double()) <= 180.);
|
||||
BOOST_ASSERT(std::abs(toFloating(projected_v.lon).operator double()) <= 180.);
|
||||
BOOST_ASSERT(std::abs(toFloating(projected_v.lat).operator double()) <= 180.);
|
||||
BOOST_ASSERT(std::abs(toFloating(projected_u.lon).operator double()) <=
|
||||
180.);
|
||||
BOOST_ASSERT(std::abs(toFloating(projected_u.lat).operator double()) <=
|
||||
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 =
|
||||
std::min(rectangle.min_lon, std::min(projected_u.lon, projected_v.lon));
|
||||
rectangle.max_lon =
|
||||
std::max(rectangle.max_lon, std::max(projected_u.lon, projected_v.lon));
|
||||
rectangle.min_lon =
|
||||
std::min(rectangle.min_lon, std::min(projected_u.lon, projected_v.lon));
|
||||
rectangle.max_lon =
|
||||
std::max(rectangle.max_lon, std::max(projected_u.lon, projected_v.lon));
|
||||
|
||||
rectangle.min_lat =
|
||||
std::min(rectangle.min_lat, std::min(projected_u.lat, projected_v.lat));
|
||||
rectangle.max_lat =
|
||||
std::max(rectangle.max_lat, std::max(projected_u.lat, projected_v.lat));
|
||||
rectangle.min_lat =
|
||||
std::min(rectangle.min_lat, std::min(projected_u.lat, projected_v.lat));
|
||||
rectangle.max_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
|
||||
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);
|
||||
}
|
||||
|
||||
tree_nodes_in_level.emplace_back(current_node);
|
||||
}
|
||||
leaf_node_file.flush();
|
||||
leaf_node_file.close();
|
||||
|
||||
std::uint32_t processing_level = 0;
|
||||
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,
|
||||
storage::io::FileWriter::HasNoFingerprint);
|
||||
{
|
||||
// open tree file
|
||||
storage::io::FileWriter tree_node_file(tree_node_filename,
|
||||
storage::io::FileWriter::HasNoFingerprint);
|
||||
|
||||
std::uint64_t size_of_tree = m_search_tree.size();
|
||||
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
||||
std::uint64_t size_of_tree = m_search_tree.size();
|
||||
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
||||
|
||||
tree_node_file.WriteOne(size_of_tree);
|
||||
tree_node_file.WriteFrom(&m_search_tree[0], size_of_tree);
|
||||
tree_node_file.WriteOne(size_of_tree);
|
||||
tree_node_file.WriteFrom(&m_search_tree[0], size_of_tree);
|
||||
}
|
||||
|
||||
MapLeafNodesFile(leaf_node_filename);
|
||||
}
|
||||
@@ -379,6 +385,24 @@ class StaticRTree
|
||||
std::size_t num_leaves = m_leaves_region.size() / sizeof(LeafNode);
|
||||
auto data_ptr = m_leaves_region.data();
|
||||
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);
|
||||
}
|
||||
catch (const std::exception &exc)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "osrm",
|
||||
"version": "5.7.1",
|
||||
"version": "5.7.4",
|
||||
"private": false,
|
||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||
"dependencies": {
|
||||
|
||||
@@ -53,7 +53,7 @@ double findTotalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_ste
|
||||
// both angles are in the same direction, the total turn gets increased
|
||||
//
|
||||
// a ---- b
|
||||
// \
|
||||
// \
|
||||
// c
|
||||
// |
|
||||
// d
|
||||
@@ -315,11 +315,6 @@ RouteSteps collapseTurnInstructions(RouteSteps steps)
|
||||
if (entersRoundabout(current_step->maneuver.instruction) ||
|
||||
staysOnRoundabout(current_step->maneuver.instruction))
|
||||
{
|
||||
// Skip over all instructions within the roundabout
|
||||
for (; current_step + 1 != steps.end(); ++current_step)
|
||||
if (leavesRoundabout(current_step->maneuver.instruction))
|
||||
break;
|
||||
|
||||
// are we done for good?
|
||||
if (current_step + 1 == steps.end())
|
||||
break;
|
||||
|
||||
@@ -171,9 +171,11 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
if (!guidance::haveSameMode(exit_step, prev_step))
|
||||
{
|
||||
BOOST_ASSERT(leavesRoundabout(exit_step.maneuver.instruction));
|
||||
prev_step.maneuver.instruction = exit_step.maneuver.instruction;
|
||||
if (!entersRoundabout(prev_step.maneuver.instruction))
|
||||
prev_step.maneuver.exit = exit_step.maneuver.exit;
|
||||
{
|
||||
prev_step.maneuver.instruction = exit_step.maneuver.instruction;
|
||||
}
|
||||
prev_step.maneuver.exit = exit_step.maneuver.exit;
|
||||
exit_step.maneuver.instruction.type = TurnType::Notification;
|
||||
step_index--;
|
||||
}
|
||||
@@ -198,9 +200,12 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
{
|
||||
auto &propagation_step = steps[propagation_index];
|
||||
auto &next_step = steps[propagation_index + 1];
|
||||
propagation_step.ElongateBy(next_step);
|
||||
propagation_step.maneuver.exit = next_step.maneuver.exit;
|
||||
next_step.Invalidate();
|
||||
if (guidance::haveSameMode(propagation_step, next_step))
|
||||
{
|
||||
propagation_step.ElongateBy(next_step);
|
||||
propagation_step.maneuver.exit = next_step.maneuver.exit;
|
||||
next_step.Invalidate();
|
||||
}
|
||||
|
||||
if (entersRoundabout(propagation_step.maneuver.instruction))
|
||||
{
|
||||
|
||||
@@ -173,7 +173,7 @@ void ExtractionContainers::WriteCharData(const std::string &file_name)
|
||||
util::UnbufferedLog log;
|
||||
log << "writing street name 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;
|
||||
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 "util/geojson_debug_logger.hpp"
|
||||
|
||||
#include "util/assert.hpp"
|
||||
#include "util/bearing.hpp"
|
||||
#include "util/coordinate_calculation.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
|
||||
const auto uturn_bearing = [&]() {
|
||||
// uturn is a pair of {edge id, bearing}
|
||||
const auto uturn = [&]() {
|
||||
const auto merge_entry = std::find_if(
|
||||
performed_merges.begin(), performed_merges.end(), [&uturn_edge_itr](const auto entry) {
|
||||
return entry.merged_eid == uturn_edge_itr->eid;
|
||||
@@ -291,7 +293,8 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
||||
normalized_intersection.end(),
|
||||
[&](const IntersectionShapeData &road) { return road.eid == merged_into_id; });
|
||||
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
|
||||
{
|
||||
@@ -301,7 +304,9 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
||||
connect_to_previous_node);
|
||||
BOOST_ASSERT(uturn_edge_at_normalized_intersection_itr !=
|
||||
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(
|
||||
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 =
|
||||
@@ -369,8 +374,22 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
||||
std::end(intersection_view),
|
||||
std::mem_fn(&IntersectionViewData::CompareByAngle));
|
||||
|
||||
BOOST_ASSERT(intersection_view[0].angle >= 0. &&
|
||||
intersection_view[0].angle < std::numeric_limits<double>::epsilon());
|
||||
// Move entering_via_edge to intersection front and place all roads prior entering_via_edge
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "extractor/guidance/roundabout_handler.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
|
||||
#include "util/assert.hpp"
|
||||
#include "util/bearing.hpp"
|
||||
#include "util/coordinate_calculation.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.
|
||||
// This workaround handles cases in which an exit precedes and entry. The resulting
|
||||
// u-turn against the roundabout direction is invalidated.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "util/indexed_data.hpp"
|
||||
#include "util/exception.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <boost/test/test_case_template.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>
|
||||
void test_rw(const Offsets &offsets, const Data &data)
|
||||
{
|
||||
std::stringstream sstr;
|
||||
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
|
||||
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)
|
||||
{
|
||||
std::stringstream sstr;
|
||||
auto path = boost::filesystem::unique_path();
|
||||
std::string name_data = "hellostringview";
|
||||
std::vector<std::uint32_t> name_offsets = {0, 5, 11, 15};
|
||||
|
||||
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());
|
||||
|
||||
BOOST_CHECK_EQUAL(indexed_data.at(0), "hello");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "util/name_table.hpp"
|
||||
#include "util/exception.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/test/test_case_template.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::stringstream sstr;
|
||||
NameTable::IndexedData indexed_data;
|
||||
std::vector<unsigned char> name_char_data;
|
||||
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());
|
||||
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user