Move files in src/ include/
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BEARING_HPP
|
||||
#define BEARING_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace bearing
|
||||
{
|
||||
inline std::string get(const double heading)
|
||||
{
|
||||
BOOST_ASSERT(heading >= 0);
|
||||
BOOST_ASSERT(heading <= 360);
|
||||
|
||||
if (heading <= 22.5)
|
||||
{
|
||||
return "N";
|
||||
}
|
||||
if (heading <= 67.5)
|
||||
{
|
||||
return "NE";
|
||||
}
|
||||
if (heading <= 112.5)
|
||||
{
|
||||
return "E";
|
||||
}
|
||||
if (heading <= 157.5)
|
||||
{
|
||||
return "SE";
|
||||
}
|
||||
if (heading <= 202.5)
|
||||
{
|
||||
return "S";
|
||||
}
|
||||
if (heading <= 247.5)
|
||||
{
|
||||
return "SW";
|
||||
}
|
||||
if (heading <= 292.5)
|
||||
{
|
||||
return "W";
|
||||
}
|
||||
if (heading <= 337.5)
|
||||
{
|
||||
return "NW";
|
||||
}
|
||||
return "N";
|
||||
}
|
||||
|
||||
// Checks whether A is between B-range and B+range, all modulo 360
|
||||
// e.g. A = 5, B = 5, range = 10 == true
|
||||
// A = -6, B = 5, range = 10 == false
|
||||
// A = -2, B = 355, range = 10 == true
|
||||
// A = 6, B = 355, range = 10 == false
|
||||
// A = 355, B = -2, range = 10 == true
|
||||
//
|
||||
// @param A the bearing to check, in degrees, 0-359, 0=north
|
||||
// @param B the bearing to check against, in degrees, 0-359, 0=north
|
||||
// @param range the number of degrees either side of B that A will still match
|
||||
// @return true if B-range <= A <= B+range, modulo 360
|
||||
inline bool CheckInBounds(const int A, const int B, const int range)
|
||||
{
|
||||
|
||||
if (range >= 180)
|
||||
return true;
|
||||
if (range <= 0)
|
||||
return false;
|
||||
|
||||
// Map both bearings into positive modulo 360 space
|
||||
const int normalized_B = (B < 0) ? (B % 360) + 360 : (B % 360);
|
||||
const int normalized_A = (A < 0) ? (A % 360) + 360 : (A % 360);
|
||||
|
||||
if (normalized_B - range < 0)
|
||||
{
|
||||
return (normalized_B - range + 360 <= normalized_A && normalized_A < 360) ||
|
||||
(0 <= normalized_A && normalized_A <= normalized_B + range);
|
||||
}
|
||||
else if (normalized_B + range > 360)
|
||||
{
|
||||
return (normalized_B - range <= normalized_A && normalized_A < 360) ||
|
||||
(0 <= normalized_A && normalized_A <= normalized_B + range - 360);
|
||||
}
|
||||
else
|
||||
{
|
||||
return normalized_B - range <= normalized_A && normalized_A <= normalized_B + range;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BEARING_HPP
|
||||
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BINARY_HEAP_H
|
||||
#define BINARY_HEAP_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
template <typename NodeID, typename Key> class ArrayStorage
|
||||
{
|
||||
public:
|
||||
explicit ArrayStorage(size_t size) : positions(size, 0) {}
|
||||
|
||||
~ArrayStorage() {}
|
||||
|
||||
Key &operator[](NodeID node) { return positions[node]; }
|
||||
|
||||
Key peek_index(const NodeID node) const { return positions[node]; }
|
||||
|
||||
void Clear() {}
|
||||
|
||||
private:
|
||||
std::vector<Key> positions;
|
||||
};
|
||||
|
||||
template <typename NodeID, typename Key> class MapStorage
|
||||
{
|
||||
public:
|
||||
explicit MapStorage(size_t) {}
|
||||
|
||||
Key &operator[](NodeID node) { return nodes[node]; }
|
||||
|
||||
void Clear() { nodes.clear(); }
|
||||
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
const auto iter = nodes.find(node);
|
||||
if (nodes.end() != iter)
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return std::numeric_limits<Key>::max();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<NodeID, Key> nodes;
|
||||
};
|
||||
|
||||
template <typename NodeID, typename Key> class UnorderedMapStorage
|
||||
{
|
||||
public:
|
||||
explicit UnorderedMapStorage(size_t) { nodes.rehash(1000); }
|
||||
|
||||
Key &operator[](const NodeID node) { return nodes[node]; }
|
||||
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
const auto iter = nodes.find(node);
|
||||
if (std::end(nodes) != iter)
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return std::numeric_limits<Key>::max();
|
||||
}
|
||||
|
||||
Key const &operator[](const NodeID node) const
|
||||
{
|
||||
auto iter = nodes.find(node);
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void Clear() { nodes.clear(); }
|
||||
|
||||
private:
|
||||
std::unordered_map<NodeID, Key> nodes;
|
||||
};
|
||||
|
||||
template <typename NodeID,
|
||||
typename Key,
|
||||
typename Weight,
|
||||
typename Data,
|
||||
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
||||
class BinaryHeap
|
||||
{
|
||||
private:
|
||||
BinaryHeap(const BinaryHeap &right);
|
||||
void operator=(const BinaryHeap &right);
|
||||
|
||||
public:
|
||||
using WeightType = Weight;
|
||||
using DataType = Data;
|
||||
|
||||
explicit BinaryHeap(size_t maxID) : node_index(maxID) { Clear(); }
|
||||
|
||||
void Clear()
|
||||
{
|
||||
heap.resize(1);
|
||||
inserted_nodes.clear();
|
||||
heap[0].weight = std::numeric_limits<Weight>::min();
|
||||
node_index.Clear();
|
||||
}
|
||||
|
||||
std::size_t Size() const { return (heap.size() - 1); }
|
||||
|
||||
bool Empty() const { return 0 == Size(); }
|
||||
|
||||
void Insert(NodeID node, Weight weight, const Data &data)
|
||||
{
|
||||
HeapElement element;
|
||||
element.index = static_cast<NodeID>(inserted_nodes.size());
|
||||
element.weight = weight;
|
||||
const Key key = static_cast<Key>(heap.size());
|
||||
heap.emplace_back(element);
|
||||
inserted_nodes.emplace_back(node, key, weight, data);
|
||||
node_index[node] = element.index;
|
||||
Upheap(key);
|
||||
CheckHeap();
|
||||
}
|
||||
|
||||
Data &GetData(NodeID node)
|
||||
{
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].data;
|
||||
}
|
||||
|
||||
Data const &GetData(NodeID node) const
|
||||
{
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].data;
|
||||
}
|
||||
|
||||
Weight &GetKey(NodeID node)
|
||||
{
|
||||
const Key index = node_index[node];
|
||||
return inserted_nodes[index].weight;
|
||||
}
|
||||
|
||||
bool WasRemoved(const NodeID node) const
|
||||
{
|
||||
BOOST_ASSERT(WasInserted(node));
|
||||
const Key index = node_index.peek_index(node);
|
||||
return inserted_nodes[index].key == 0;
|
||||
}
|
||||
|
||||
bool WasInserted(const NodeID node) const
|
||||
{
|
||||
const auto index = node_index.peek_index(node);
|
||||
if (index >= static_cast<decltype(index)>(inserted_nodes.size()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return inserted_nodes[index].node == node;
|
||||
}
|
||||
|
||||
NodeID Min() const
|
||||
{
|
||||
BOOST_ASSERT(heap.size() > 1);
|
||||
return inserted_nodes[heap[1].index].node;
|
||||
}
|
||||
|
||||
Weight MinKey() const {
|
||||
BOOST_ASSERT(heap.size() > 1);
|
||||
return heap[1].weight;
|
||||
}
|
||||
|
||||
NodeID DeleteMin()
|
||||
{
|
||||
BOOST_ASSERT(heap.size() > 1);
|
||||
const Key removedIndex = heap[1].index;
|
||||
heap[1] = heap[heap.size() - 1];
|
||||
heap.pop_back();
|
||||
if (heap.size() > 1)
|
||||
{
|
||||
Downheap(1);
|
||||
}
|
||||
inserted_nodes[removedIndex].key = 0;
|
||||
CheckHeap();
|
||||
return inserted_nodes[removedIndex].node;
|
||||
}
|
||||
|
||||
void DeleteAll()
|
||||
{
|
||||
auto iend = heap.end();
|
||||
for (auto i = heap.begin() + 1; i != iend; ++i)
|
||||
{
|
||||
inserted_nodes[i->index].key = 0;
|
||||
}
|
||||
heap.resize(1);
|
||||
heap[0].weight = (std::numeric_limits<Weight>::min)();
|
||||
}
|
||||
|
||||
void DecreaseKey(NodeID node, Weight weight)
|
||||
{
|
||||
BOOST_ASSERT(std::numeric_limits<NodeID>::max() != node);
|
||||
const Key &index = node_index.peek_index(node);
|
||||
Key &key = inserted_nodes[index].key;
|
||||
BOOST_ASSERT(key >= 0);
|
||||
|
||||
inserted_nodes[index].weight = weight;
|
||||
heap[key].weight = weight;
|
||||
Upheap(key);
|
||||
CheckHeap();
|
||||
}
|
||||
|
||||
private:
|
||||
class HeapNode
|
||||
{
|
||||
public:
|
||||
HeapNode(NodeID n, Key k, Weight w, Data d) : node(n), key(k), weight(w), data(std::move(d))
|
||||
{
|
||||
}
|
||||
|
||||
NodeID node;
|
||||
Key key;
|
||||
Weight weight;
|
||||
Data data;
|
||||
};
|
||||
struct HeapElement
|
||||
{
|
||||
Key index;
|
||||
Weight weight;
|
||||
};
|
||||
|
||||
std::vector<HeapNode> inserted_nodes;
|
||||
std::vector<HeapElement> heap;
|
||||
IndexStorage node_index;
|
||||
|
||||
void Downheap(Key key)
|
||||
{
|
||||
const Key droppingIndex = heap[key].index;
|
||||
const Weight weight = heap[key].weight;
|
||||
const Key heap_size = static_cast<Key>(heap.size());
|
||||
Key nextKey = key << 1;
|
||||
while (nextKey < heap_size)
|
||||
{
|
||||
const Key nextKeyOther = nextKey + 1;
|
||||
if ((nextKeyOther < heap_size) && (heap[nextKey].weight > heap[nextKeyOther].weight))
|
||||
{
|
||||
nextKey = nextKeyOther;
|
||||
}
|
||||
if (weight <= heap[nextKey].weight)
|
||||
{
|
||||
break;
|
||||
}
|
||||
heap[key] = heap[nextKey];
|
||||
inserted_nodes[heap[key].index].key = key;
|
||||
key = nextKey;
|
||||
nextKey <<= 1;
|
||||
}
|
||||
heap[key].index = droppingIndex;
|
||||
heap[key].weight = weight;
|
||||
inserted_nodes[droppingIndex].key = key;
|
||||
}
|
||||
|
||||
void Upheap(Key key)
|
||||
{
|
||||
const Key risingIndex = heap[key].index;
|
||||
const Weight weight = heap[key].weight;
|
||||
Key nextKey = key >> 1;
|
||||
while (heap[nextKey].weight > weight)
|
||||
{
|
||||
BOOST_ASSERT(nextKey != 0);
|
||||
heap[key] = heap[nextKey];
|
||||
inserted_nodes[heap[key].index].key = key;
|
||||
key = nextKey;
|
||||
nextKey >>= 1;
|
||||
}
|
||||
heap[key].index = risingIndex;
|
||||
heap[key].weight = weight;
|
||||
inserted_nodes[risingIndex].key = key;
|
||||
}
|
||||
|
||||
void CheckHeap()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (std::size_t i = 2; i < heap.size(); ++i)
|
||||
{
|
||||
BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BINARY_HEAP_H
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CAST_HPP
|
||||
#define CAST_HPP
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
||||
namespace cast
|
||||
{
|
||||
template <typename Enumeration>
|
||||
inline auto enum_to_underlying(Enumeration const value) ->
|
||||
typename std::underlying_type<Enumeration>::type
|
||||
{
|
||||
return static_cast<typename std::underlying_type<Enumeration>::type>(value);
|
||||
}
|
||||
|
||||
template <typename T, int Precision = 6> inline std::string to_string_with_precision(const T x)
|
||||
{
|
||||
static_assert(std::is_arithmetic<T>::value, "integral or floating point type required");
|
||||
|
||||
std::ostringstream out;
|
||||
out << std::fixed << std::setprecision(Precision) << x;
|
||||
auto rv = out.str();
|
||||
|
||||
// Javascript has no separation of float / int, digits without a '.' are integral typed
|
||||
// X.Y.0 -> X.Y
|
||||
// X.0 -> X
|
||||
boost::trim_right_if(rv, boost::is_any_of("0"));
|
||||
boost::trim_right_if(rv, boost::is_any_of("."));
|
||||
// Note:
|
||||
// - assumes the locale to use '.' as digit separator
|
||||
// - this is not identical to: trim_right_if(rv, is_any_of('0 .'))
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CAST_HPP
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef COMPUTE_ANGLE_HPP
|
||||
#define COMPUTE_ANGLE_HPP
|
||||
|
||||
struct FixedPointCoordinate;
|
||||
|
||||
struct ComputeAngle
|
||||
{
|
||||
// Get angle of line segment (A,C)->(C,B)
|
||||
// atan2 magic, formerly cosine theorem
|
||||
static double OfThreeFixedPointCoordinates(const FixedPointCoordinate &first,
|
||||
const FixedPointCoordinate &second,
|
||||
const FixedPointCoordinate &third) noexcept;
|
||||
};
|
||||
|
||||
#endif // COMPUTE_ANGLE_HPP
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CONTAINER_HPP
|
||||
#define CONTAINER_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// Culled by SFINAE if reserve does not exist or is not accessible
|
||||
template <typename T>
|
||||
constexpr auto has_resize_method(T &t) noexcept -> decltype(t.resize(0), bool())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Used as fallback when SFINAE culls the template method
|
||||
constexpr bool has_resize_method(...) noexcept { return false; }
|
||||
}
|
||||
|
||||
template <typename Container> void sort_unique_resize(Container &vector) noexcept
|
||||
{
|
||||
std::sort(std::begin(vector), std::end(vector));
|
||||
const auto number_of_unique_elements =
|
||||
std::unique(std::begin(vector), std::end(vector)) - std::begin(vector);
|
||||
if (detail::has_resize_method(vector))
|
||||
{
|
||||
vector.resize(number_of_unique_elements);
|
||||
}
|
||||
}
|
||||
|
||||
// template <typename T> inline void sort_unique_resize_shrink_vector(std::vector<T> &vector)
|
||||
// {
|
||||
// sort_unique_resize(vector);
|
||||
// vector.shrink_to_fit();
|
||||
// }
|
||||
|
||||
// template <typename T> inline void remove_consecutive_duplicates_from_vector(std::vector<T>
|
||||
// &vector)
|
||||
// {
|
||||
// const auto number_of_unique_elements = std::unique(vector.begin(), vector.end()) -
|
||||
// vector.begin();
|
||||
// vector.resize(number_of_unique_elements);
|
||||
// }
|
||||
|
||||
template <typename ForwardIterator, typename Function>
|
||||
Function for_each_pair(ForwardIterator begin, ForwardIterator end, Function function)
|
||||
{
|
||||
if (begin == end)
|
||||
{
|
||||
return function;
|
||||
}
|
||||
|
||||
auto next = begin;
|
||||
next = std::next(next);
|
||||
|
||||
while (next != end)
|
||||
{
|
||||
function(*begin, *next);
|
||||
begin = std::next(begin);
|
||||
next = std::next(next);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
template <class ContainerT, typename Function>
|
||||
Function for_each_pair(ContainerT &container, Function function)
|
||||
{
|
||||
return for_each_pair(std::begin(container), std::end(container), function);
|
||||
}
|
||||
|
||||
template <class Container> void append_to_container(Container &&) {}
|
||||
|
||||
template <class Container, typename T, typename... Args>
|
||||
void append_to_container(Container &&container, T value, Args &&... args)
|
||||
{
|
||||
container.emplace_back(value);
|
||||
append_to_container(std::forward<Container>(container), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace osrm
|
||||
#endif /* CONTAINER_HPP */
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef COORDINATE_CALCULATION
|
||||
#define COORDINATE_CALCULATION
|
||||
|
||||
struct FixedPointCoordinate;
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace coordinate_calculation
|
||||
{
|
||||
double
|
||||
haversine_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
double haversine_distance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
float great_circle_distance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
float great_circle_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
void lat_or_lon_to_string(const int value, std::string &output);
|
||||
|
||||
float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location);
|
||||
|
||||
float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
float perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate);
|
||||
|
||||
float perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
float deg_to_rad(const float degree);
|
||||
float rad_to_deg(const float radian);
|
||||
|
||||
float bearing(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
}
|
||||
|
||||
#endif // COORDINATE_CALCULATION
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DATASTORE_OPTIONS_HPP
|
||||
#define DATASTORE_OPTIONS_HPP
|
||||
|
||||
#include "util/version.hpp"
|
||||
#include "ini_file.hpp"
|
||||
#include "osrm_exception.hpp"
|
||||
#include "simple_logger.hpp"
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
// generate boost::program_options object for the routing part
|
||||
bool GenerateDataStoreOptions(const int argc, const char *argv[], std::unordered_map<std::string, boost::filesystem::path> &paths)
|
||||
{
|
||||
// declare a group of options that will be allowed only on command line
|
||||
boost::program_options::options_description generic_options("Options");
|
||||
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
|
||||
"springclean,s", "Remove all regions in shared memory")(
|
||||
"config,c", boost::program_options::value<boost::filesystem::path>(&paths["config"])
|
||||
->default_value("server.ini"),
|
||||
"Path to a configuration file");
|
||||
|
||||
// declare a group of options that will be allowed both on command line
|
||||
// as well as in a config file
|
||||
boost::program_options::options_description config_options("Configuration");
|
||||
config_options.add_options()(
|
||||
"hsgrdata", boost::program_options::value<boost::filesystem::path>(&paths["hsgrdata"]),
|
||||
".hsgr file")("nodesdata",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["nodesdata"]),
|
||||
".nodes file")(
|
||||
"edgesdata", boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
|
||||
".edges file")("geometry",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["geometry"]),
|
||||
".geometry file")(
|
||||
"ramindex", boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
|
||||
".ramIndex file")(
|
||||
"fileindex", boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
|
||||
".fileIndex file")("core",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["core"]),
|
||||
".core file")(
|
||||
"namesdata", boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
|
||||
".names file")("timestamp",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["timestamp"]),
|
||||
".timestamp file");
|
||||
|
||||
// hidden options, will be allowed both on command line and in config
|
||||
// file, but will not be shown to the user
|
||||
boost::program_options::options_description hidden_options("Hidden options");
|
||||
hidden_options.add_options()(
|
||||
"base,b", boost::program_options::value<boost::filesystem::path>(&paths["base"]),
|
||||
"base path to .osrm file");
|
||||
|
||||
// positional option
|
||||
boost::program_options::positional_options_description positional_options;
|
||||
positional_options.add("base", 1);
|
||||
|
||||
// combine above options for parsing
|
||||
boost::program_options::options_description cmdline_options;
|
||||
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description config_file_options;
|
||||
config_file_options.add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description visible_options(
|
||||
boost::filesystem::basename(argv[0]) + " [<options>] <configuration>");
|
||||
visible_options.add(generic_options).add(config_options);
|
||||
|
||||
// parse command line options
|
||||
boost::program_options::variables_map option_variables;
|
||||
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
|
||||
.options(cmdline_options)
|
||||
.positional(positional_options)
|
||||
.run(),
|
||||
option_variables);
|
||||
|
||||
if (option_variables.count("version"))
|
||||
{
|
||||
SimpleLogger().Write() << OSRM_VERSION;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (option_variables.count("help"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::program_options::notify(option_variables);
|
||||
|
||||
const bool parameter_present =
|
||||
(paths.find("hsgrdata") != paths.end() &&
|
||||
!paths.find("hsgrdata")->second.string().empty()) ||
|
||||
(paths.find("nodesdata") != paths.end() &&
|
||||
!paths.find("nodesdata")->second.string().empty()) ||
|
||||
(paths.find("edgesdata") != paths.end() &&
|
||||
!paths.find("edgesdata")->second.string().empty()) ||
|
||||
(paths.find("geometry") != paths.end() &&
|
||||
!paths.find("geometry")->second.string().empty()) ||
|
||||
(paths.find("ramindex") != paths.end() &&
|
||||
!paths.find("ramindex")->second.string().empty()) ||
|
||||
(paths.find("fileindex") != paths.end() &&
|
||||
!paths.find("fileindex")->second.string().empty()) ||
|
||||
(paths.find("core") != paths.end() && !paths.find("core")->second.string().empty()) ||
|
||||
(paths.find("timestamp") != paths.end() &&
|
||||
!paths.find("timestamp")->second.string().empty());
|
||||
|
||||
if (parameter_present)
|
||||
{
|
||||
if ((paths.find("config") != paths.end() &&
|
||||
boost::filesystem::is_regular_file(paths.find("config")->second)) ||
|
||||
option_variables.count("base"))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "conflicting parameters";
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// parse config file
|
||||
auto path_iterator = paths.find("config");
|
||||
if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) &&
|
||||
!option_variables.count("base"))
|
||||
{
|
||||
SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string();
|
||||
std::string ini_file_contents = read_file_lower_content(path_iterator->second);
|
||||
std::stringstream config_stream(ini_file_contents);
|
||||
boost::program_options::store(parse_config_file(config_stream, config_file_options),
|
||||
option_variables);
|
||||
boost::program_options::notify(option_variables);
|
||||
}
|
||||
else if (option_variables.count("base"))
|
||||
{
|
||||
path_iterator = paths.find("base");
|
||||
BOOST_ASSERT(paths.end() != path_iterator);
|
||||
std::string base_string = path_iterator->second.string();
|
||||
|
||||
path_iterator = paths.find("hsgrdata");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".hsgr";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("nodesdata");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".nodes";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("edgesdata");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".edges";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("geometry");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".geometry";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("ramindex");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".ramIndex";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("fileindex");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".fileIndex";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("core");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".core";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("namesdata");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".names";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("timestamp");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".timestamp";
|
||||
}
|
||||
}
|
||||
|
||||
path_iterator = paths.find("hsgrdata");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception("valid .hsgr file must be specified");
|
||||
}
|
||||
|
||||
path_iterator = paths.find("nodesdata");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception("valid .nodes file must be specified");
|
||||
}
|
||||
|
||||
path_iterator = paths.find("edgesdata");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception("valid .edges file must be specified");
|
||||
}
|
||||
|
||||
path_iterator = paths.find("geometry");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception("valid .geometry file must be specified");
|
||||
}
|
||||
|
||||
path_iterator = paths.find("ramindex");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception("valid .ramindex file must be specified");
|
||||
}
|
||||
|
||||
path_iterator = paths.find("fileindex");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception("valid .fileindex file must be specified");
|
||||
}
|
||||
|
||||
path_iterator = paths.find("namesdata");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception("valid .names file must be specified");
|
||||
}
|
||||
|
||||
path_iterator = paths.find("timestamp");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception("valid .timestamp file must be specified");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* DATASTORE_OPTIONS_HPP */
|
||||
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DEALLOCATING_VECTOR_HPP
|
||||
#define DEALLOCATING_VECTOR_HPP
|
||||
|
||||
#include "../util/integer_range.hpp"
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
template <typename ElementT> struct ConstDeallocatingVectorIteratorState
|
||||
{
|
||||
ConstDeallocatingVectorIteratorState()
|
||||
: index(std::numeric_limits<std::size_t>::max()), bucket_list(nullptr)
|
||||
{
|
||||
}
|
||||
explicit ConstDeallocatingVectorIteratorState(const ConstDeallocatingVectorIteratorState &r)
|
||||
: index(r.index), bucket_list(r.bucket_list)
|
||||
{
|
||||
}
|
||||
explicit ConstDeallocatingVectorIteratorState(const std::size_t idx,
|
||||
const std::vector<ElementT *> *input_list)
|
||||
: index(idx), bucket_list(input_list)
|
||||
{
|
||||
}
|
||||
std::size_t index;
|
||||
const std::vector<ElementT *> *bucket_list;
|
||||
|
||||
ConstDeallocatingVectorIteratorState &operator=(const ConstDeallocatingVectorIteratorState &other)
|
||||
{
|
||||
index = other.index;
|
||||
bucket_list = other.bucket_list;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ElementT> struct DeallocatingVectorIteratorState
|
||||
{
|
||||
DeallocatingVectorIteratorState()
|
||||
: index(std::numeric_limits<std::size_t>::max()), bucket_list(nullptr)
|
||||
{
|
||||
}
|
||||
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r)
|
||||
: index(r.index), bucket_list(r.bucket_list)
|
||||
{
|
||||
}
|
||||
explicit DeallocatingVectorIteratorState(const std::size_t idx,
|
||||
std::vector<ElementT *> *input_list)
|
||||
: index(idx), bucket_list(input_list)
|
||||
{
|
||||
}
|
||||
std::size_t index;
|
||||
std::vector<ElementT *> *bucket_list;
|
||||
|
||||
DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &other)
|
||||
{
|
||||
index = other.index;
|
||||
bucket_list = other.bucket_list;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
|
||||
class ConstDeallocatingVectorIterator
|
||||
: public boost::iterator_facade<ConstDeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>,
|
||||
ElementT,
|
||||
std::random_access_iterator_tag>
|
||||
{
|
||||
ConstDeallocatingVectorIteratorState<ElementT> current_state;
|
||||
|
||||
public:
|
||||
ConstDeallocatingVectorIterator() {}
|
||||
ConstDeallocatingVectorIterator(std::size_t idx, const std::vector<ElementT *> *input_list)
|
||||
: current_state(idx, input_list)
|
||||
{
|
||||
}
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
void advance(std::size_t n) { current_state.index += n; }
|
||||
|
||||
void increment() { advance(1); }
|
||||
|
||||
void decrement() { advance(-1); }
|
||||
|
||||
bool equal(ConstDeallocatingVectorIterator const &other) const
|
||||
{
|
||||
return current_state.index == other.current_state.index;
|
||||
}
|
||||
|
||||
std::ptrdiff_t distance_to(ConstDeallocatingVectorIterator const &other) const
|
||||
{
|
||||
// it is important to implement it 'other minus this'. otherwise sorting breaks
|
||||
return other.current_state.index - current_state.index;
|
||||
}
|
||||
|
||||
ElementT &dereference() const
|
||||
{
|
||||
const std::size_t current_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t current_index = current_state.index % ELEMENTS_PER_BLOCK;
|
||||
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
||||
}
|
||||
|
||||
ElementT &operator[](const std::size_t index) const
|
||||
{
|
||||
const std::size_t current_bucket = (index + current_state.index) / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t current_index = (index + current_state.index) % ELEMENTS_PER_BLOCK;
|
||||
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
|
||||
class DeallocatingVectorIterator
|
||||
: public boost::iterator_facade<DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>,
|
||||
ElementT,
|
||||
std::random_access_iterator_tag>
|
||||
{
|
||||
DeallocatingVectorIteratorState<ElementT> current_state;
|
||||
|
||||
public:
|
||||
DeallocatingVectorIterator() {}
|
||||
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> *input_list)
|
||||
: current_state(idx, input_list)
|
||||
{
|
||||
}
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
void advance(std::size_t n) { current_state.index += n; }
|
||||
|
||||
void increment() { advance(1); }
|
||||
|
||||
void decrement() { advance(-1); }
|
||||
|
||||
bool equal(DeallocatingVectorIterator const &other) const
|
||||
{
|
||||
return current_state.index == other.current_state.index;
|
||||
}
|
||||
|
||||
std::ptrdiff_t distance_to(DeallocatingVectorIterator const &other) const
|
||||
{
|
||||
// it is important to implement it 'other minus this'. otherwise sorting breaks
|
||||
return other.current_state.index - current_state.index;
|
||||
}
|
||||
|
||||
ElementT &dereference() const
|
||||
{
|
||||
const std::size_t current_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t current_index = current_state.index % ELEMENTS_PER_BLOCK;
|
||||
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
||||
}
|
||||
|
||||
ElementT &operator[](const std::size_t index) const
|
||||
{
|
||||
const std::size_t current_bucket = (index + current_state.index) / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t current_index = (index + current_state.index) % ELEMENTS_PER_BLOCK;
|
||||
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
|
||||
class DeallocatingVectorRemoveIterator
|
||||
: public boost::iterator_facade<DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>,
|
||||
ElementT,
|
||||
boost::forward_traversal_tag>
|
||||
{
|
||||
DeallocatingVectorIteratorState<ElementT> current_state;
|
||||
|
||||
public:
|
||||
DeallocatingVectorRemoveIterator(std::size_t idx, std::vector<ElementT *> *input_list)
|
||||
: current_state(idx, input_list)
|
||||
{
|
||||
}
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
void increment()
|
||||
{
|
||||
const std::size_t old_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
||||
|
||||
++current_state.index;
|
||||
const std::size_t new_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
||||
if (old_bucket != new_bucket)
|
||||
{
|
||||
// delete old bucket entry
|
||||
if (nullptr != current_state.bucket_list->at(old_bucket))
|
||||
{
|
||||
delete[] current_state.bucket_list->at(old_bucket);
|
||||
current_state.bucket_list->at(old_bucket) = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool equal(DeallocatingVectorRemoveIterator const &other) const
|
||||
{
|
||||
return current_state.index == other.current_state.index;
|
||||
}
|
||||
|
||||
std::ptrdiff_t distance_to(DeallocatingVectorRemoveIterator const &other) const
|
||||
{
|
||||
return other.current_state.index - current_state.index;
|
||||
}
|
||||
|
||||
ElementT &dereference() const
|
||||
{
|
||||
const std::size_t current_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t current_index = current_state.index % ELEMENTS_PER_BLOCK;
|
||||
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
|
||||
class DeallocatingVector;
|
||||
|
||||
template<typename T, std::size_t S>
|
||||
void swap(DeallocatingVector<T, S>& lhs, DeallocatingVector<T, S>& rhs);
|
||||
|
||||
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK = 8388608 / sizeof(ElementT)>
|
||||
class DeallocatingVector
|
||||
{
|
||||
std::size_t current_size;
|
||||
std::vector<ElementT *> bucket_list;
|
||||
|
||||
public:
|
||||
using iterator = DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||
using const_iterator = ConstDeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||
|
||||
// this forward-only iterator deallocates all buckets that have been visited
|
||||
using deallocation_iterator = DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||
|
||||
DeallocatingVector() : current_size(0)
|
||||
{
|
||||
bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||
}
|
||||
|
||||
~DeallocatingVector() { clear(); }
|
||||
|
||||
friend void swap<>(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK>& lhs, DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK>& rhs);
|
||||
|
||||
void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &other)
|
||||
{
|
||||
std::swap(current_size, other.current_size);
|
||||
bucket_list.swap(other.bucket_list);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
// Delete[]'ing ptr's to all Buckets
|
||||
for (auto bucket : bucket_list)
|
||||
{
|
||||
if (nullptr != bucket)
|
||||
{
|
||||
delete[] bucket;
|
||||
bucket = nullptr;
|
||||
}
|
||||
}
|
||||
bucket_list.clear();
|
||||
bucket_list.shrink_to_fit();
|
||||
current_size = 0;
|
||||
}
|
||||
|
||||
void push_back(const ElementT &element)
|
||||
{
|
||||
const std::size_t current_capacity = capacity();
|
||||
if (current_size == current_capacity)
|
||||
{
|
||||
bucket_list.push_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||
}
|
||||
|
||||
std::size_t current_index = size() % ELEMENTS_PER_BLOCK;
|
||||
bucket_list.back()[current_index] = element;
|
||||
++current_size;
|
||||
}
|
||||
|
||||
template <typename... Ts> void emplace_back(Ts &&... element)
|
||||
{
|
||||
const std::size_t current_capacity = capacity();
|
||||
if (current_size == current_capacity)
|
||||
{
|
||||
bucket_list.push_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||
}
|
||||
|
||||
const std::size_t current_index = size() % ELEMENTS_PER_BLOCK;
|
||||
bucket_list.back()[current_index] = ElementT(std::forward<Ts>(element)...);
|
||||
++current_size;
|
||||
}
|
||||
|
||||
void reserve(const std::size_t) const { /* don't do anything */}
|
||||
|
||||
void resize(const std::size_t new_size)
|
||||
{
|
||||
if (new_size >= current_size)
|
||||
{
|
||||
while (capacity() < new_size)
|
||||
{
|
||||
bucket_list.push_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // down-size
|
||||
const std::size_t number_of_necessary_buckets = 1 + (new_size / ELEMENTS_PER_BLOCK);
|
||||
for (const auto bucket_index :
|
||||
osrm::irange(number_of_necessary_buckets, bucket_list.size()))
|
||||
{
|
||||
if (nullptr != bucket_list[bucket_index])
|
||||
{
|
||||
delete[] bucket_list[bucket_index];
|
||||
}
|
||||
}
|
||||
bucket_list.resize(number_of_necessary_buckets);
|
||||
}
|
||||
current_size = new_size;
|
||||
}
|
||||
|
||||
std::size_t size() const { return current_size; }
|
||||
|
||||
std::size_t capacity() const { return bucket_list.size() * ELEMENTS_PER_BLOCK; }
|
||||
|
||||
iterator begin() { return iterator(static_cast<std::size_t>(0), &bucket_list); }
|
||||
|
||||
iterator end() { return iterator(size(), &bucket_list); }
|
||||
|
||||
deallocation_iterator dbegin()
|
||||
{
|
||||
return deallocation_iterator(static_cast<std::size_t>(0), &bucket_list);
|
||||
}
|
||||
|
||||
deallocation_iterator dend() { return deallocation_iterator(size(), &bucket_list); }
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return const_iterator(static_cast<std::size_t>(0), &bucket_list);
|
||||
}
|
||||
|
||||
const_iterator end() const { return const_iterator(size(), &bucket_list); }
|
||||
|
||||
ElementT &operator[](const std::size_t index)
|
||||
{
|
||||
const std::size_t _bucket = index / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t _index = index % ELEMENTS_PER_BLOCK;
|
||||
return (bucket_list[_bucket][_index]);
|
||||
}
|
||||
|
||||
ElementT &operator[](const std::size_t index) const
|
||||
{
|
||||
const std::size_t _bucket = index / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t _index = index % ELEMENTS_PER_BLOCK;
|
||||
return (bucket_list[_bucket][_index]);
|
||||
}
|
||||
|
||||
ElementT &back() const
|
||||
{
|
||||
const std::size_t _bucket = current_size / ELEMENTS_PER_BLOCK;
|
||||
const std::size_t _index = current_size % ELEMENTS_PER_BLOCK;
|
||||
return (bucket_list[_bucket][_index]);
|
||||
}
|
||||
|
||||
template <class InputIterator> void append(InputIterator first, const InputIterator last)
|
||||
{
|
||||
InputIterator position = first;
|
||||
while (position != last)
|
||||
{
|
||||
push_back(*position);
|
||||
++position;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, std::size_t S>
|
||||
void swap(DeallocatingVector<T, S>& lhs, DeallocatingVector<T, S>& rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
#endif /* DEALLOCATING_VECTOR_HPP */
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DEBUG_GEOMETRY_H
|
||||
#define DEBUG_GEOMETRY_H
|
||||
|
||||
#include "../contractor/contractor_options.hpp"
|
||||
#include "../data_structures/query_node.hpp"
|
||||
|
||||
#ifndef DEBUG_GEOMETRY
|
||||
|
||||
inline void DEBUG_GEOMETRY_START(ContractorConfig & /* config */) {}
|
||||
inline void DEBUG_GEOMETRY_EDGE(int /* new_segment_weight */ , double /* segment_length */,
|
||||
OSMNodeID /* previous_osm_node_id */, OSMNodeID /* this_osm_node_id */) {}
|
||||
inline void DEBUG_GEOMETRY_STOP() {}
|
||||
|
||||
inline void DEBUG_TURNS_START(const std::string & /* debug_turns_filename */) {}
|
||||
inline void DEBUG_TURN( const NodeID /* node */, const std::vector<QueryNode>& /* m_node_info_list */,
|
||||
const FixedPointCoordinate & /* first_coordinate */, const int /* turn_angle */,
|
||||
const int /* turn_penalty */) {}
|
||||
inline void DEBUG_UTURN( const NodeID /* node */, const std::vector<QueryNode>& /* m_node_info_list */,
|
||||
const int /* uturn_penalty */ ) {}
|
||||
inline void DEBUG_SIGNAL( const NodeID /* node */, const std::vector<QueryNode>& /* m_node_info_list */,
|
||||
const int /* signal_penalty */ ) {}
|
||||
|
||||
inline void DEBUG_TURNS_STOP() {}
|
||||
|
||||
#else // DEBUG_GEOMETRY
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include "../include/osrm/coordinate.hpp"
|
||||
#include "../algorithms/coordinate_calculation.hpp"
|
||||
|
||||
boost::filesystem::ofstream debug_geometry_file;
|
||||
bool dg_output_debug_geometry = false;
|
||||
bool dg_first_debug_geometry = true;
|
||||
char dg_time_buffer[80];
|
||||
|
||||
boost::filesystem::ofstream dg_debug_turns_file;
|
||||
bool dg_output_turn_debug = false;
|
||||
bool dg_first_turn_debug = true;
|
||||
|
||||
inline void DEBUG_GEOMETRY_START(const ContractorConfig &config)
|
||||
{
|
||||
time_t raw_time;
|
||||
struct tm *timeinfo;
|
||||
time(&raw_time);
|
||||
timeinfo = localtime(&raw_time);
|
||||
strftime(dg_time_buffer, 80, "%Y-%m-%d %H:%M %Z", timeinfo);
|
||||
|
||||
dg_output_debug_geometry = config.debug_geometry_path != "";
|
||||
|
||||
if (dg_output_debug_geometry)
|
||||
{
|
||||
debug_geometry_file.open(config.debug_geometry_path, std::ios::binary);
|
||||
debug_geometry_file << "{\"type\":\"FeatureCollection\", \"features\":[" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
inline void DEBUG_GEOMETRY_EDGE(int new_segment_weight, double segment_length, OSMNodeID previous_osm_node_id, OSMNodeID this_osm_node_id)
|
||||
{
|
||||
if (dg_output_debug_geometry)
|
||||
{
|
||||
if (!dg_first_debug_geometry)
|
||||
debug_geometry_file << "," << std::endl;
|
||||
debug_geometry_file
|
||||
<< "{ \"type\":\"Feature\",\"properties\":{\"original\":false, "
|
||||
"\"weight\":"
|
||||
<< new_segment_weight / 10.0 << ",\"speed\":"
|
||||
<< static_cast<int>(
|
||||
std::floor((segment_length / new_segment_weight) * 10. * 3.6))
|
||||
<< ",";
|
||||
debug_geometry_file << "\"from_node\": " << previous_osm_node_id
|
||||
<< ", \"to_node\": " << this_osm_node_id << ",";
|
||||
debug_geometry_file << "\"timestamp\": \"" << dg_time_buffer << "\"},";
|
||||
debug_geometry_file
|
||||
<< "\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[!!"
|
||||
<< previous_osm_node_id << "!!],[!!" << this_osm_node_id << "!!]]}}"
|
||||
<< std::endl;
|
||||
dg_first_debug_geometry = false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void DEBUG_GEOMETRY_STOP()
|
||||
{
|
||||
if (dg_output_debug_geometry)
|
||||
{
|
||||
debug_geometry_file << std::endl << "]}" << std::endl;
|
||||
debug_geometry_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void DEBUG_TURNS_START(const std::string & debug_turns_path)
|
||||
{
|
||||
dg_output_turn_debug = debug_turns_path != "";
|
||||
if (dg_output_turn_debug)
|
||||
{
|
||||
dg_debug_turns_file.open(debug_turns_path);
|
||||
dg_debug_turns_file << "{\"type\":\"FeatureCollection\", \"features\":[" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
inline void DEBUG_SIGNAL(
|
||||
const NodeID node,
|
||||
const std::vector<QueryNode>& m_node_info_list,
|
||||
const int traffic_signal_penalty)
|
||||
{
|
||||
if (dg_output_turn_debug)
|
||||
{
|
||||
const QueryNode &nodeinfo = m_node_info_list[node];
|
||||
if (!dg_first_turn_debug) dg_debug_turns_file << "," << std::endl;
|
||||
dg_debug_turns_file << "{ \"type\":\"Feature\",\"properties\":{\"type\":\"trafficlights\",\"cost\":" << traffic_signal_penalty/10. << "},";
|
||||
dg_debug_turns_file << " \"geometry\":{\"type\":\"Point\",\"coordinates\":[" << std::setprecision(12) << nodeinfo.lon/COORDINATE_PRECISION << "," << nodeinfo.lat/COORDINATE_PRECISION << "]}}";
|
||||
dg_first_turn_debug = false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void DEBUG_UTURN(
|
||||
const NodeID node,
|
||||
const std::vector<QueryNode>& m_node_info_list,
|
||||
const int traffic_signal_penalty)
|
||||
{
|
||||
if (dg_output_turn_debug)
|
||||
{
|
||||
const QueryNode &nodeinfo = m_node_info_list[node];
|
||||
if (!dg_first_turn_debug) dg_debug_turns_file << "," << std::endl;
|
||||
dg_debug_turns_file << "{ \"type\":\"Feature\",\"properties\":{\"type\":\"trafficlights\",\"cost\":" << traffic_signal_penalty/10. << "},";
|
||||
dg_debug_turns_file << " \"geometry\":{\"type\":\"Point\",\"coordinates\":[" << std::setprecision(12) << nodeinfo.lon/COORDINATE_PRECISION << "," << nodeinfo.lat/COORDINATE_PRECISION << "]}}";
|
||||
dg_first_turn_debug = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void DEBUG_TURN(
|
||||
const NodeID node,
|
||||
const std::vector<QueryNode>& m_node_info_list,
|
||||
const FixedPointCoordinate & first_coordinate,
|
||||
const int turn_angle,
|
||||
const int turn_penalty)
|
||||
{
|
||||
if (turn_penalty > 0 && dg_output_turn_debug)
|
||||
{
|
||||
const QueryNode &v = m_node_info_list[node];
|
||||
|
||||
const float bearing_uv = coordinate_calculation::bearing(first_coordinate,v);
|
||||
float uvw_normal = bearing_uv + turn_angle/2;
|
||||
while (uvw_normal >= 360.) { uvw_normal -= 360.; }
|
||||
|
||||
if (!dg_first_turn_debug) dg_debug_turns_file << "," << std::endl;
|
||||
dg_debug_turns_file << "{ \"type\":\"Feature\",\"properties\":{\"type\":\"turn\",\"cost\":" << turn_penalty/10. << ",\"turn_angle\":" << static_cast<int>(turn_angle) << ",\"normal\":" << static_cast<int>(uvw_normal) << "},";
|
||||
dg_debug_turns_file << " \"geometry\":{\"type\":\"Point\",\"coordinates\":[" << std::setprecision(12) << v.lon/COORDINATE_PRECISION << "," << v.lat/COORDINATE_PRECISION << "]}}";
|
||||
dg_first_turn_debug = false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void DEBUG_TURNS_STOP()
|
||||
{
|
||||
if (dg_output_turn_debug)
|
||||
{
|
||||
dg_debug_turns_file << std::endl << "]}" << std::endl;
|
||||
dg_debug_turns_file.close();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DEBUG_GEOMETRY
|
||||
|
||||
|
||||
#endif // DEBUG_GEOMETRY_H
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DIST_TABLE_WRAPPER_H
|
||||
#define DIST_TABLE_WRAPPER_H
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
// This Wrapper provides an easier access to a distance table that is given as an linear vector
|
||||
|
||||
template <typename T> class DistTableWrapper
|
||||
{
|
||||
public:
|
||||
using Iterator = typename std::vector<T>::iterator;
|
||||
using ConstIterator = typename std::vector<T>::const_iterator;
|
||||
|
||||
DistTableWrapper(std::vector<T> table, std::size_t number_of_nodes)
|
||||
: table_(std::move(table)), number_of_nodes_(number_of_nodes)
|
||||
{
|
||||
BOOST_ASSERT_MSG(table.size() == 0, "table is empty");
|
||||
BOOST_ASSERT_MSG(number_of_nodes_ * number_of_nodes_ <= table_.size(),
|
||||
"number_of_nodes_ is invalid");
|
||||
};
|
||||
|
||||
std::size_t GetNumberOfNodes() const { return number_of_nodes_; }
|
||||
|
||||
std::size_t size() const { return table_.size(); }
|
||||
|
||||
EdgeWeight operator()(NodeID from, NodeID to) const
|
||||
{
|
||||
BOOST_ASSERT_MSG(from < number_of_nodes_, "from ID is out of bound");
|
||||
BOOST_ASSERT_MSG(to < number_of_nodes_, "to ID is out of bound");
|
||||
|
||||
const auto index = from * number_of_nodes_ + to;
|
||||
|
||||
BOOST_ASSERT_MSG(index < table_.size(), "index is out of bound");
|
||||
|
||||
return table_[index];
|
||||
}
|
||||
|
||||
ConstIterator begin() const { return std::begin(table_); }
|
||||
|
||||
Iterator begin() { return std::begin(table_); }
|
||||
|
||||
ConstIterator end() const { return std::end(table_); }
|
||||
|
||||
Iterator end() { return std::end(table_); }
|
||||
|
||||
NodeID GetIndexOfMaxValue() const
|
||||
{
|
||||
return std::distance(table_.begin(), std::max_element(table_.begin(), table_.end()));
|
||||
}
|
||||
|
||||
std::vector<T> GetTable() const { return table_; }
|
||||
|
||||
private:
|
||||
std::vector<T> table_;
|
||||
const std::size_t number_of_nodes_;
|
||||
};
|
||||
|
||||
#endif // DIST_TABLE_WRAPPER_H
|
||||
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNAMICGRAPH_HPP
|
||||
#define DYNAMICGRAPH_HPP
|
||||
|
||||
#include "deallocating_vector.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
template <typename EdgeDataT> class DynamicGraph
|
||||
{
|
||||
public:
|
||||
using EdgeData = EdgeDataT;
|
||||
using NodeIterator = unsigned;
|
||||
using EdgeIterator = unsigned;
|
||||
using EdgeRange = osrm::range<EdgeIterator>;
|
||||
|
||||
class InputEdge
|
||||
{
|
||||
public:
|
||||
NodeIterator source;
|
||||
NodeIterator target;
|
||||
EdgeDataT data;
|
||||
|
||||
InputEdge()
|
||||
: source(std::numeric_limits<NodeIterator>::max()),
|
||||
target(std::numeric_limits<NodeIterator>::max())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
InputEdge(NodeIterator source, NodeIterator target, Ts &&... data)
|
||||
: source(source), target(target), data(std::forward<Ts>(data)...)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const InputEdge &rhs) const
|
||||
{
|
||||
return std::tie(source, target) < std::tie(rhs.source, rhs.target);
|
||||
}
|
||||
};
|
||||
|
||||
// Constructs an empty graph with a given number of nodes.
|
||||
explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0)
|
||||
{
|
||||
node_array.reserve(number_of_nodes);
|
||||
node_array.resize(number_of_nodes);
|
||||
|
||||
edge_list.reserve(number_of_nodes * 1.1);
|
||||
edge_list.resize(number_of_nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a DynamicGraph from a list of edges sorted by source node id.
|
||||
*/
|
||||
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
|
||||
{
|
||||
// we need to cast here because DeallocatingVector does not have a valid const iterator
|
||||
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT&>(graph).begin(), const_cast<ContainerT&>(graph).end()));
|
||||
|
||||
number_of_nodes = nodes;
|
||||
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
||||
node_array.resize(number_of_nodes + 1);
|
||||
EdgeIterator edge = 0;
|
||||
EdgeIterator position = 0;
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||
{
|
||||
EdgeIterator last_edge = edge;
|
||||
while (edge < number_of_edges && graph[edge].source == node)
|
||||
{
|
||||
++edge;
|
||||
}
|
||||
node_array[node].first_edge = position;
|
||||
node_array[node].edges = edge - last_edge;
|
||||
position += node_array[node].edges;
|
||||
}
|
||||
node_array.back().first_edge = position;
|
||||
edge_list.reserve(static_cast<std::size_t>(edge_list.size() * 1.1));
|
||||
edge_list.resize(position);
|
||||
edge = 0;
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||
{
|
||||
for (const auto i : osrm::irange(node_array[node].first_edge,
|
||||
node_array[node].first_edge + node_array[node].edges))
|
||||
{
|
||||
edge_list[i].target = graph[edge].target;
|
||||
BOOST_ASSERT(edge_list[i].target < number_of_nodes);
|
||||
edge_list[i].data = graph[edge].data;
|
||||
++edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~DynamicGraph() {}
|
||||
|
||||
unsigned GetNumberOfNodes() const { return number_of_nodes; }
|
||||
|
||||
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
||||
|
||||
unsigned GetOutDegree(const NodeIterator n) const { return node_array[n].edges; }
|
||||
|
||||
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
||||
{
|
||||
unsigned degree = 0;
|
||||
for (const auto edge : osrm::irange(BeginEdges(n), EndEdges(n)))
|
||||
{
|
||||
if (!GetEdgeData(edge).reversed)
|
||||
{
|
||||
++degree;
|
||||
}
|
||||
}
|
||||
return degree;
|
||||
}
|
||||
|
||||
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(edge_list[e].target); }
|
||||
|
||||
void SetTarget(const EdgeIterator e, const NodeIterator n) { edge_list[e].target = n; }
|
||||
|
||||
EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_list[e].data; }
|
||||
|
||||
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_list[e].data; }
|
||||
|
||||
EdgeIterator BeginEdges(const NodeIterator n) const
|
||||
{
|
||||
return EdgeIterator(node_array[n].first_edge);
|
||||
}
|
||||
|
||||
EdgeIterator EndEdges(const NodeIterator n) const
|
||||
{
|
||||
return EdgeIterator(node_array[n].first_edge + node_array[n].edges);
|
||||
}
|
||||
|
||||
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
||||
{
|
||||
return osrm::irange(BeginEdges(node), EndEdges(node));
|
||||
}
|
||||
|
||||
NodeIterator InsertNode()
|
||||
{
|
||||
node_array.emplace_back(node_array.back());
|
||||
number_of_nodes += 1;
|
||||
|
||||
return number_of_nodes;
|
||||
}
|
||||
|
||||
// adds an edge. Invalidates edge iterators for the source node
|
||||
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
|
||||
{
|
||||
Node &node = node_array[from];
|
||||
EdgeIterator newFirstEdge = node.edges + node.first_edge;
|
||||
if (newFirstEdge >= edge_list.size() || !isDummy(newFirstEdge))
|
||||
{
|
||||
if (node.first_edge != 0 && isDummy(node.first_edge - 1))
|
||||
{
|
||||
node.first_edge--;
|
||||
edge_list[node.first_edge] = edge_list[node.first_edge + node.edges];
|
||||
}
|
||||
else
|
||||
{
|
||||
EdgeIterator newFirstEdge = (EdgeIterator)edge_list.size();
|
||||
unsigned newSize = node.edges * 1.1 + 2;
|
||||
EdgeIterator requiredCapacity = newSize + edge_list.size();
|
||||
EdgeIterator oldCapacity = edge_list.capacity();
|
||||
if (requiredCapacity >= oldCapacity)
|
||||
{
|
||||
edge_list.reserve(requiredCapacity * 1.1);
|
||||
}
|
||||
edge_list.resize(edge_list.size() + newSize);
|
||||
for (const auto i : osrm::irange(0u, node.edges))
|
||||
{
|
||||
edge_list[newFirstEdge + i] = edge_list[node.first_edge + i];
|
||||
makeDummy(node.first_edge + i);
|
||||
}
|
||||
for (const auto i : osrm::irange(node.edges + 1, newSize))
|
||||
{
|
||||
makeDummy(newFirstEdge + i);
|
||||
}
|
||||
node.first_edge = newFirstEdge;
|
||||
}
|
||||
}
|
||||
Edge &edge = edge_list[node.first_edge + node.edges];
|
||||
edge.target = to;
|
||||
edge.data = data;
|
||||
++number_of_edges;
|
||||
++node.edges;
|
||||
return EdgeIterator(node.first_edge + node.edges);
|
||||
}
|
||||
|
||||
// removes an edge. Invalidates edge iterators for the source node
|
||||
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
|
||||
{
|
||||
Node &node = node_array[source];
|
||||
--number_of_edges;
|
||||
--node.edges;
|
||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
|
||||
const unsigned last = node.first_edge + node.edges;
|
||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
|
||||
// swap with last edge
|
||||
edge_list[e] = edge_list[last];
|
||||
makeDummy(last);
|
||||
}
|
||||
|
||||
// removes all edges (source,target)
|
||||
int32_t DeleteEdgesTo(const NodeIterator source, const NodeIterator target)
|
||||
{
|
||||
int32_t deleted = 0;
|
||||
for (EdgeIterator i = BeginEdges(source), iend = EndEdges(source); i < iend - deleted; ++i)
|
||||
{
|
||||
if (edge_list[i].target == target)
|
||||
{
|
||||
do
|
||||
{
|
||||
deleted++;
|
||||
edge_list[i] = edge_list[iend - deleted];
|
||||
makeDummy(iend - deleted);
|
||||
} while (i < iend - deleted && edge_list[i].target == target);
|
||||
}
|
||||
}
|
||||
|
||||
number_of_edges -= deleted;
|
||||
node_array[source].edges -= deleted;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
// searches for a specific edge
|
||||
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
for (const auto i : osrm::irange(BeginEdges(from), EndEdges(from)))
|
||||
{
|
||||
if (to == edge_list[i].target)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return SPECIAL_EDGEID;
|
||||
}
|
||||
|
||||
// searches for a specific edge
|
||||
EdgeIterator FindSmallestEdge(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
EdgeIterator smallest_edge = SPECIAL_EDGEID;
|
||||
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
|
||||
for (auto edge : GetAdjacentEdgeRange(from))
|
||||
{
|
||||
const NodeID target = GetTarget(edge);
|
||||
const EdgeWeight weight = GetEdgeData(edge).distance;
|
||||
if (target == to && weight < smallest_weight)
|
||||
{
|
||||
smallest_edge = edge;
|
||||
smallest_weight = weight;
|
||||
}
|
||||
}
|
||||
return smallest_edge;
|
||||
}
|
||||
|
||||
EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
EdgeIterator tmp = FindEdge(from, to);
|
||||
return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
|
||||
}
|
||||
|
||||
EdgeIterator
|
||||
FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const
|
||||
{
|
||||
EdgeIterator current_iterator = FindEdge(from, to);
|
||||
if (SPECIAL_NODEID == current_iterator)
|
||||
{
|
||||
current_iterator = FindEdge(to, from);
|
||||
if (SPECIAL_NODEID != current_iterator)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return current_iterator;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool isDummy(const EdgeIterator edge) const
|
||||
{
|
||||
return edge_list[edge].target == (std::numeric_limits<NodeIterator>::max)();
|
||||
}
|
||||
|
||||
void makeDummy(const EdgeIterator edge)
|
||||
{
|
||||
edge_list[edge].target = (std::numeric_limits<NodeIterator>::max)();
|
||||
}
|
||||
|
||||
struct Node
|
||||
{
|
||||
// index of the first edge
|
||||
EdgeIterator first_edge;
|
||||
// amount of edges
|
||||
unsigned edges;
|
||||
};
|
||||
|
||||
struct Edge
|
||||
{
|
||||
NodeIterator target;
|
||||
EdgeDataT data;
|
||||
};
|
||||
|
||||
NodeIterator number_of_nodes;
|
||||
std::atomic_uint number_of_edges;
|
||||
|
||||
std::vector<Node> node_array;
|
||||
DeallocatingVector<Edge> edge_list;
|
||||
};
|
||||
|
||||
#endif // DYNAMICGRAPH_HPP
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FINGERPRINT_H
|
||||
#define FINGERPRINT_H
|
||||
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
// implements a singleton, i.e. there is one and only one conviguration object
|
||||
class FingerPrint
|
||||
{
|
||||
public:
|
||||
static FingerPrint GetValid();
|
||||
const boost::uuids::uuid &GetFingerPrint() const;
|
||||
bool IsMagicNumberOK(const FingerPrint &other) const;
|
||||
bool TestGraphUtil(const FingerPrint &other) const;
|
||||
bool TestPrepare(const FingerPrint &other) const;
|
||||
bool TestRTree(const FingerPrint &other) const;
|
||||
bool TestQueryObjects(const FingerPrint &other) const;
|
||||
|
||||
private:
|
||||
unsigned magic_number;
|
||||
char md5_prepare[33];
|
||||
char md5_tree[33];
|
||||
char md5_graph[33];
|
||||
char md5_objects[33];
|
||||
|
||||
// initialize to {6ba7b810-9dad-11d1-80b4-00c04fd430c8}
|
||||
boost::uuids::uuid named_uuid;
|
||||
|
||||
};
|
||||
|
||||
static_assert(std::is_trivial<FingerPrint>::value, "FingerPrint needs to be trivial.");
|
||||
|
||||
|
||||
#endif /* FingerPrint_H */
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "util/osrm_exception.hpp"
|
||||
|
||||
#include <boost/uuid/name_generator.hpp>
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#cmakedefine MD5PREPARE "${MD5PREPARE}"
|
||||
#cmakedefine MD5RTREE "${MD5RTREE}"
|
||||
#cmakedefine MD5GRAPH "${MD5GRAPH}"
|
||||
#cmakedefine MD5OBJECTS "${MD5OBJECTS}"
|
||||
|
||||
FingerPrint FingerPrint::GetValid()
|
||||
{
|
||||
FingerPrint fingerprint;
|
||||
|
||||
fingerprint.magic_number = 1297240911;
|
||||
fingerprint.md5_prepare[32] = fingerprint.md5_tree[32] = fingerprint.md5_graph[32] = fingerprint.md5_objects[32] = '\0';
|
||||
|
||||
// 6ba7b810-9dad-11d1-80b4-00c04fd430c8 is a Well Known UUID representing the DNS
|
||||
// namespace. Its use here indicates that we own this part of the UUID space
|
||||
// in the DNS realm. *Usually*, we would then generate a UUID based on "something.project-osrm.org",
|
||||
// but this whole class is a hack. Anyway, named_uuid needs to be initialized to something
|
||||
// before it can be used, and this is as good as anything else for these purposes.
|
||||
fingerprint.named_uuid = boost::uuids::string_generator()( "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}");
|
||||
|
||||
boost::uuids::name_generator gen(fingerprint.named_uuid);
|
||||
std::string temp_string;
|
||||
|
||||
std::memcpy(fingerprint.md5_prepare, MD5PREPARE, 32);
|
||||
temp_string += fingerprint.md5_prepare;
|
||||
std::memcpy(fingerprint.md5_tree, MD5RTREE, 32);
|
||||
temp_string += fingerprint.md5_tree;
|
||||
std::memcpy(fingerprint.md5_graph, MD5GRAPH, 32);
|
||||
temp_string += fingerprint.md5_graph;
|
||||
std::memcpy(fingerprint.md5_objects, MD5OBJECTS, 32);
|
||||
temp_string += fingerprint.md5_objects;
|
||||
|
||||
fingerprint.named_uuid = gen(temp_string);
|
||||
|
||||
return fingerprint;
|
||||
}
|
||||
|
||||
const boost::uuids::uuid &FingerPrint::GetFingerPrint() const { return named_uuid; }
|
||||
|
||||
bool FingerPrint::IsMagicNumberOK(const FingerPrint& other) const { return other.magic_number == magic_number; }
|
||||
|
||||
bool FingerPrint::TestGraphUtil(const FingerPrint &other) const
|
||||
{
|
||||
if (!IsMagicNumberOK(other))
|
||||
{
|
||||
throw osrm::exception("hsgr input file misses magic number. Check or reprocess the file");
|
||||
}
|
||||
return std::equal(md5_graph, md5_graph + 32, other.md5_graph);
|
||||
}
|
||||
|
||||
bool FingerPrint::TestPrepare(const FingerPrint &other) const
|
||||
{
|
||||
if (!IsMagicNumberOK(other))
|
||||
{
|
||||
throw osrm::exception("osrm input file misses magic number. Check or reprocess the file");
|
||||
}
|
||||
return std::equal(md5_prepare, md5_prepare + 32, other.md5_prepare);
|
||||
}
|
||||
|
||||
bool FingerPrint::TestRTree(const FingerPrint &other) const
|
||||
{
|
||||
if (!IsMagicNumberOK(other))
|
||||
{
|
||||
throw osrm::exception("r-tree input file misses magic number. Check or reprocess the file");
|
||||
}
|
||||
return std::equal(md5_tree, md5_tree + 32, other.md5_tree);
|
||||
}
|
||||
|
||||
bool FingerPrint::TestQueryObjects(const FingerPrint &other) const
|
||||
{
|
||||
if (!IsMagicNumberOK(other))
|
||||
{
|
||||
throw osrm::exception("missing magic number. Check or reprocess the file");
|
||||
}
|
||||
return std::equal(md5_objects, md5_objects + 32, other.md5_objects);
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FIXED_POINT_NUMBER_HPP
|
||||
#define FIXED_POINT_NUMBER_HPP
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
// implements an binary based fixed point number type
|
||||
template <unsigned FractionalBitSize,
|
||||
bool use_64_bits = false,
|
||||
bool is_unsigned = false,
|
||||
bool truncate_results = false>
|
||||
class FixedPointNumber
|
||||
{
|
||||
static_assert(FractionalBitSize > 0, "FractionalBitSize must be greater than 0");
|
||||
static_assert(FractionalBitSize <= 32, "FractionalBitSize must at most 32");
|
||||
|
||||
typename std::conditional<use_64_bits, int64_t, int32_t>::type m_fixed_point_state;
|
||||
constexpr static const decltype(m_fixed_point_state) PRECISION = 1 << FractionalBitSize;
|
||||
|
||||
// state signage encapsulates whether the state should either represent a
|
||||
// signed or an unsigned floating point number
|
||||
using state_signage =
|
||||
typename std::conditional<is_unsigned,
|
||||
typename std::make_unsigned<decltype(m_fixed_point_state)>::type,
|
||||
decltype(m_fixed_point_state)>::type;
|
||||
|
||||
public:
|
||||
FixedPointNumber() : m_fixed_point_state(0) {}
|
||||
|
||||
// the type is either initialized with a floating point value or an
|
||||
// integral state. Anything else will throw at compile-time.
|
||||
template <class T>
|
||||
constexpr FixedPointNumber(const T &&input) noexcept
|
||||
: m_fixed_point_state(static_cast<decltype(m_fixed_point_state)>(
|
||||
std::round(std::forward<const T>(input) * PRECISION)))
|
||||
{
|
||||
static_assert(
|
||||
std::is_floating_point<T>::value || std::is_integral<T>::value,
|
||||
"FixedPointNumber needs to be initialized with floating point or integral value");
|
||||
}
|
||||
|
||||
// get max value
|
||||
template <typename T,
|
||||
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||
constexpr static auto max() noexcept -> T
|
||||
{
|
||||
return static_cast<T>(std::numeric_limits<state_signage>::max()) / PRECISION;
|
||||
}
|
||||
|
||||
// get min value
|
||||
template <typename T,
|
||||
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||
constexpr static auto min() noexcept -> T
|
||||
{
|
||||
return static_cast<T>(1) / PRECISION;
|
||||
}
|
||||
|
||||
// get lowest value
|
||||
template <typename T,
|
||||
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||
constexpr static auto lowest() noexcept -> T
|
||||
{
|
||||
return static_cast<T>(std::numeric_limits<state_signage>::min()) / PRECISION;
|
||||
}
|
||||
|
||||
// cast to floating point type T, return value
|
||||
template <typename T,
|
||||
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||
explicit operator const T() const noexcept
|
||||
{
|
||||
// casts to external type (signed or unsigned) and then to float
|
||||
return static_cast<T>(static_cast<state_signage>(m_fixed_point_state)) / PRECISION;
|
||||
}
|
||||
|
||||
// warn about cast to integral type T, its disabled for good reason
|
||||
template <typename T, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
|
||||
explicit operator T() const
|
||||
{
|
||||
static_assert(std::is_integral<T>::value,
|
||||
"casts to integral types have been disabled on purpose");
|
||||
}
|
||||
|
||||
// compare, ie. sort fixed-point numbers
|
||||
bool operator<(const FixedPointNumber &other) const noexcept
|
||||
{
|
||||
return m_fixed_point_state < other.m_fixed_point_state;
|
||||
}
|
||||
|
||||
// equality, ie. sort fixed-point numbers
|
||||
bool operator==(const FixedPointNumber &other) const noexcept
|
||||
{
|
||||
return m_fixed_point_state == other.m_fixed_point_state;
|
||||
}
|
||||
|
||||
bool operator!=(const FixedPointNumber &other) const { return !(*this == other); }
|
||||
bool operator>(const FixedPointNumber &other) const { return other < *this; }
|
||||
bool operator<=(const FixedPointNumber &other) const { return !(other < *this); }
|
||||
bool operator>=(const FixedPointNumber &other) const { return !(*this < other); }
|
||||
|
||||
// arithmetic operators
|
||||
FixedPointNumber operator+(const FixedPointNumber &other) const noexcept
|
||||
{
|
||||
FixedPointNumber tmp = *this;
|
||||
tmp.m_fixed_point_state += other.m_fixed_point_state;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
FixedPointNumber &operator+=(const FixedPointNumber &other) noexcept
|
||||
{
|
||||
this->m_fixed_point_state += other.m_fixed_point_state;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FixedPointNumber operator-(const FixedPointNumber &other) const noexcept
|
||||
{
|
||||
FixedPointNumber tmp = *this;
|
||||
tmp.m_fixed_point_state -= other.m_fixed_point_state;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
FixedPointNumber &operator-=(const FixedPointNumber &other) noexcept
|
||||
{
|
||||
this->m_fixed_point_state -= other.m_fixed_point_state;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FixedPointNumber operator*(const FixedPointNumber &other) const noexcept
|
||||
{
|
||||
int64_t temp = this->m_fixed_point_state;
|
||||
temp *= other.m_fixed_point_state;
|
||||
|
||||
// rounding!
|
||||
if (!truncate_results)
|
||||
{
|
||||
temp = temp + ((temp & 1 << (FractionalBitSize - 1)) << 1);
|
||||
}
|
||||
temp >>= FractionalBitSize;
|
||||
FixedPointNumber tmp;
|
||||
tmp.m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
FixedPointNumber &operator*=(const FixedPointNumber &other) noexcept
|
||||
{
|
||||
int64_t temp = this->m_fixed_point_state;
|
||||
temp *= other.m_fixed_point_state;
|
||||
|
||||
// rounding!
|
||||
if (!truncate_results)
|
||||
{
|
||||
temp = temp + ((temp & 1 << (FractionalBitSize - 1)) << 1);
|
||||
}
|
||||
temp >>= FractionalBitSize;
|
||||
this->m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FixedPointNumber operator/(const FixedPointNumber &other) const noexcept
|
||||
{
|
||||
int64_t temp = this->m_fixed_point_state;
|
||||
temp <<= FractionalBitSize;
|
||||
temp /= static_cast<int64_t>(other.m_fixed_point_state);
|
||||
FixedPointNumber tmp;
|
||||
tmp.m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
FixedPointNumber &operator/=(const FixedPointNumber &other) noexcept
|
||||
{
|
||||
int64_t temp = this->m_fixed_point_state;
|
||||
temp <<= FractionalBitSize;
|
||||
temp /= static_cast<int64_t>(other.m_fixed_point_state);
|
||||
FixedPointNumber tmp;
|
||||
this->m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(4 == sizeof(FixedPointNumber<1>), "FP19 has wrong size != 4");
|
||||
}
|
||||
#endif // FIXED_POINT_NUMBER_HPP
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FLOATING_POINT_HPP
|
||||
#define FLOATING_POINT_HPP
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
template <typename FloatT> bool epsilon_compare(const FloatT number1, const FloatT number2)
|
||||
{
|
||||
static_assert(std::is_floating_point<FloatT>::value, "type must be floating point");
|
||||
return (std::abs(number1 - number2) < std::numeric_limits<FloatT>::epsilon());
|
||||
}
|
||||
}
|
||||
|
||||
#endif // FLOATING_POINT_HPP
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GRAPH_LOADER_HPP
|
||||
#define GRAPH_LOADER_HPP
|
||||
|
||||
#include "fingerprint.hpp"
|
||||
#include "osrm_exception.hpp"
|
||||
#include "simple_logger.hpp"
|
||||
#include "../data_structures/external_memory_node.hpp"
|
||||
#include "../data_structures/import_edge.hpp"
|
||||
#include "../data_structures/query_node.hpp"
|
||||
#include "../data_structures/restriction.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <fstream>
|
||||
#include <ios>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Reads the .restrictions file and loads it to a vector.
|
||||
* The since the restrictions reference nodes using their external node id,
|
||||
* we need to renumber it to the new internal id.
|
||||
*/
|
||||
unsigned loadRestrictionsFromFile(std::istream &input_stream,
|
||||
std::vector<TurnRestriction> &restriction_list)
|
||||
{
|
||||
const FingerPrint fingerprint_valid = FingerPrint::GetValid();
|
||||
FingerPrint fingerprint_loaded;
|
||||
unsigned number_of_usable_restrictions = 0;
|
||||
input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
|
||||
if (!fingerprint_loaded.TestPrepare(fingerprint_valid))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n"
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
input_stream.read((char *)&number_of_usable_restrictions, sizeof(unsigned));
|
||||
restriction_list.resize(number_of_usable_restrictions);
|
||||
if (number_of_usable_restrictions > 0)
|
||||
{
|
||||
input_stream.read((char *)restriction_list.data(),
|
||||
number_of_usable_restrictions * sizeof(TurnRestriction));
|
||||
}
|
||||
|
||||
return number_of_usable_restrictions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the beginning of an .osrm file and produces:
|
||||
* - list of barrier nodes
|
||||
* - list of traffic lights
|
||||
* - nodes indexed by their internal (non-osm) id
|
||||
*/
|
||||
NodeID loadNodesFromFile(std::istream &input_stream,
|
||||
std::vector<NodeID> &barrier_node_list,
|
||||
std::vector<NodeID> &traffic_light_node_list,
|
||||
std::vector<QueryNode> &node_array)
|
||||
{
|
||||
const FingerPrint fingerprint_valid = FingerPrint::GetValid();
|
||||
FingerPrint fingerprint_loaded;
|
||||
input_stream.read(reinterpret_cast<char *>(&fingerprint_loaded), sizeof(FingerPrint));
|
||||
|
||||
if (!fingerprint_loaded.TestPrepare(fingerprint_valid))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n"
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
NodeID n;
|
||||
input_stream.read(reinterpret_cast<char *>(&n), sizeof(NodeID));
|
||||
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
|
||||
|
||||
ExternalMemoryNode current_node;
|
||||
for (NodeID i = 0; i < n; ++i)
|
||||
{
|
||||
input_stream.read(reinterpret_cast<char *>(¤t_node), sizeof(ExternalMemoryNode));
|
||||
node_array.emplace_back(current_node.lat, current_node.lon, current_node.node_id);
|
||||
if (current_node.barrier)
|
||||
{
|
||||
barrier_node_list.emplace_back(i);
|
||||
}
|
||||
if (current_node.traffic_lights)
|
||||
{
|
||||
traffic_light_node_list.emplace_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
// tighten vector sizes
|
||||
barrier_node_list.shrink_to_fit();
|
||||
traffic_light_node_list.shrink_to_fit();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a .osrm file and produces the edges.
|
||||
*/
|
||||
NodeID loadEdgesFromFile(std::istream &input_stream, std::vector<NodeBasedEdge> &edge_list)
|
||||
{
|
||||
EdgeID m;
|
||||
input_stream.read(reinterpret_cast<char *>(&m), sizeof(unsigned));
|
||||
edge_list.resize(m);
|
||||
SimpleLogger().Write() << " and " << m << " edges ";
|
||||
|
||||
input_stream.read((char *)edge_list.data(), m * sizeof(NodeBasedEdge));
|
||||
|
||||
BOOST_ASSERT(edge_list.size() > 0);
|
||||
|
||||
#ifndef NDEBUG
|
||||
SimpleLogger().Write() << "Validating loaded edges...";
|
||||
tbb::parallel_sort(edge_list.begin(), edge_list.end(),
|
||||
[](const NodeBasedEdge &lhs, const NodeBasedEdge &rhs)
|
||||
{
|
||||
return (lhs.source < rhs.source) ||
|
||||
(lhs.source == rhs.source && lhs.target < rhs.target);
|
||||
});
|
||||
for (auto i = 1u; i < edge_list.size(); ++i)
|
||||
{
|
||||
const auto &edge = edge_list[i];
|
||||
const auto &prev_edge = edge_list[i - 1];
|
||||
|
||||
BOOST_ASSERT_MSG(edge.weight > 0, "loaded null weight");
|
||||
BOOST_ASSERT_MSG(edge.forward, "edge must be oriented in forward direction");
|
||||
BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded non-accessible");
|
||||
|
||||
BOOST_ASSERT_MSG(edge.source != edge.target, "loaded edges contain a loop");
|
||||
BOOST_ASSERT_MSG(edge.source != prev_edge.source || edge.target != prev_edge.target,
|
||||
"loaded edges contain a multi edge");
|
||||
}
|
||||
#endif
|
||||
|
||||
SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
template <typename NodeT, typename EdgeT>
|
||||
unsigned readHSGRFromStream(const boost::filesystem::path &hsgr_file,
|
||||
std::vector<NodeT> &node_list,
|
||||
std::vector<EdgeT> &edge_list,
|
||||
unsigned *check_sum)
|
||||
{
|
||||
if (!boost::filesystem::exists(hsgr_file))
|
||||
{
|
||||
throw osrm::exception("hsgr file does not exist");
|
||||
}
|
||||
if (0 == boost::filesystem::file_size(hsgr_file))
|
||||
{
|
||||
throw osrm::exception("hsgr file is empty");
|
||||
}
|
||||
|
||||
boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary);
|
||||
|
||||
const FingerPrint fingerprint_valid = FingerPrint::GetValid();
|
||||
FingerPrint fingerprint_loaded;
|
||||
hsgr_input_stream.read(reinterpret_cast<char *>(&fingerprint_loaded), sizeof(FingerPrint));
|
||||
if (!fingerprint_loaded.TestGraphUtil(fingerprint_valid))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build.\n"
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
unsigned number_of_nodes = 0;
|
||||
unsigned number_of_edges = 0;
|
||||
hsgr_input_stream.read(reinterpret_cast<char *>(check_sum), sizeof(unsigned));
|
||||
hsgr_input_stream.read(reinterpret_cast<char *>(&number_of_nodes), sizeof(unsigned));
|
||||
BOOST_ASSERT_MSG(0 != number_of_nodes, "number of nodes is zero");
|
||||
hsgr_input_stream.read(reinterpret_cast<char *>(&number_of_edges), sizeof(unsigned));
|
||||
|
||||
SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes
|
||||
<< ", number_of_edges: " << number_of_edges;
|
||||
|
||||
// BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
|
||||
node_list.resize(number_of_nodes);
|
||||
hsgr_input_stream.read(reinterpret_cast<char *>(&node_list[0]),
|
||||
number_of_nodes * sizeof(NodeT));
|
||||
|
||||
edge_list.resize(number_of_edges);
|
||||
if (number_of_edges > 0)
|
||||
{
|
||||
hsgr_input_stream.read(reinterpret_cast<char *>(&edge_list[0]),
|
||||
number_of_edges * sizeof(EdgeT));
|
||||
}
|
||||
hsgr_input_stream.close();
|
||||
|
||||
return number_of_nodes;
|
||||
}
|
||||
|
||||
#endif // GRAPH_LOADER_HPP
|
||||
@@ -0,0 +1,94 @@
|
||||
#ifndef GRAPH_UTILS_HPP
|
||||
#define GRAPH_UTILS_HPP
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <vector>
|
||||
|
||||
/// This function checks if the graph (consisting of directed edges) is undirected
|
||||
template<typename GraphT>
|
||||
bool isUndirectedGraph(const GraphT& graph)
|
||||
{
|
||||
for (auto source = 0u; source < graph.GetNumberOfNodes(); ++source)
|
||||
{
|
||||
for (auto edge = graph.BeginEdges(source); edge < graph.EndEdges(source); ++edge)
|
||||
{
|
||||
const auto& data = graph.GetEdgeData(edge);
|
||||
|
||||
auto target = graph.GetTarget(edge);
|
||||
BOOST_ASSERT(target != SPECIAL_NODEID);
|
||||
|
||||
bool found_reverse = false;
|
||||
for (auto rev_edge = graph.BeginEdges(target); rev_edge < graph.EndEdges(target); ++rev_edge)
|
||||
{
|
||||
auto rev_target = graph.GetTarget(rev_edge);
|
||||
BOOST_ASSERT(rev_target != SPECIAL_NODEID);
|
||||
|
||||
if (rev_target != source)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT_MSG(!found_reverse, "Found more than one reverse edge");
|
||||
found_reverse = true;
|
||||
}
|
||||
|
||||
if (!found_reverse)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// Since DynamicGraph assumes directed edges we have to make sure we transformed
|
||||
/// the compressed edge format into single directed edges. We do this to make sure
|
||||
/// every node also knows its incoming edges, not only its outgoing edges and use the reversed=true
|
||||
/// flag to indicate which is which.
|
||||
///
|
||||
/// We do the transformation in the following way:
|
||||
///
|
||||
/// if the edge (a, b) is split:
|
||||
/// 1. this edge must be in only one direction, so its a --> b
|
||||
/// 2. there must be another directed edge b --> a somewhere in the data
|
||||
/// if the edge (a, b) is not split:
|
||||
/// 1. this edge be on of a --> b od a <-> b
|
||||
/// (a <-- b gets reducted to b --> a)
|
||||
/// 2. a --> b will be transformed to a --> b and b <-- a
|
||||
/// 3. a <-> b will be transformed to a --> b and b --> a
|
||||
template<typename OutputEdgeT, typename InputEdgeT, typename FunctorT>
|
||||
std::vector<OutputEdgeT> directedEdgesFromCompressed(const std::vector<InputEdgeT>& input_edge_list, FunctorT copy_data)
|
||||
{
|
||||
std::vector<OutputEdgeT> output_edge_list;
|
||||
|
||||
OutputEdgeT edge;
|
||||
for (const auto& input_edge : input_edge_list)
|
||||
{
|
||||
// edges that are not forward get converted by flipping the end points
|
||||
BOOST_ASSERT(input_edge.forward);
|
||||
|
||||
edge.source = input_edge.source;
|
||||
edge.target = input_edge.target;
|
||||
edge.data.reversed = false;
|
||||
|
||||
BOOST_ASSERT(edge.source != edge.target);
|
||||
|
||||
copy_data(edge, input_edge);
|
||||
|
||||
output_edge_list.push_back(edge);
|
||||
|
||||
if (!input_edge.is_split)
|
||||
{
|
||||
std::swap(edge.source, edge.target);
|
||||
edge.data.reversed = !input_edge.backward;
|
||||
output_edge_list.push_back(edge);
|
||||
}
|
||||
}
|
||||
|
||||
return output_edge_list;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HILBERT_VALUE_HPP
|
||||
#define HILBERT_VALUE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
||||
|
||||
struct FixedPointCoordinate;
|
||||
|
||||
class HilbertCode
|
||||
{
|
||||
public:
|
||||
uint64_t operator()(const FixedPointCoordinate ¤t_coordinate) const;
|
||||
HilbertCode() {}
|
||||
HilbertCode(const HilbertCode &) = delete;
|
||||
|
||||
private:
|
||||
inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) const;
|
||||
inline void TransposeCoordinate(uint32_t *X) const;
|
||||
};
|
||||
|
||||
#endif /* HILBERT_VALUE_HPP */
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef INI_FILE_HPP
|
||||
#define INI_FILE_HPP
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// support old capitalized option names by down-casing them with a regex replace
|
||||
std::string read_file_lower_content(const boost::filesystem::path &path)
|
||||
{
|
||||
boost::filesystem::fstream config_stream(path);
|
||||
std::string ini_file_content((std::istreambuf_iterator<char>(config_stream)),
|
||||
std::istreambuf_iterator<char>());
|
||||
std::transform(std::begin(ini_file_content), std::end(ini_file_content),
|
||||
std::begin(ini_file_content), ::tolower);
|
||||
return ini_file_content;
|
||||
}
|
||||
}
|
||||
#endif // INI_FILE_HPP
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef INTEGER_RANGE_HPP
|
||||
#define INTEGER_RANGE_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
template <typename Integer> class range
|
||||
{
|
||||
private:
|
||||
const Integer last;
|
||||
Integer iter;
|
||||
|
||||
public:
|
||||
range(Integer start, Integer end) noexcept : last(end), iter(start)
|
||||
{
|
||||
BOOST_ASSERT_MSG(start <= end, "backwards counting ranges not suppoted");
|
||||
static_assert(std::is_integral<Integer>::value, "range type must be integral");
|
||||
}
|
||||
|
||||
// Iterable functions
|
||||
const range &begin() const noexcept { return *this; }
|
||||
const range &end() const noexcept { return *this; }
|
||||
Integer front() const noexcept { return iter; }
|
||||
Integer back() const noexcept { return last - 1; }
|
||||
std::size_t size() const noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(last - iter);
|
||||
}
|
||||
|
||||
// Iterator functions
|
||||
bool operator!=(const range &) const noexcept { return iter < last; }
|
||||
void operator++() noexcept { ++iter; }
|
||||
Integer operator*() const noexcept { return iter; }
|
||||
};
|
||||
|
||||
// convenience function to construct an integer range with type deduction
|
||||
template <typename Integer>
|
||||
range<Integer>
|
||||
irange(const Integer first,
|
||||
const Integer last,
|
||||
typename std::enable_if<std::is_integral<Integer>::value>::type * = 0) noexcept
|
||||
{
|
||||
return range<Integer>(first, last);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // INTEGER_RANGE_HPP
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ISO_8601_DURATION_PARSER_HPP
|
||||
#define ISO_8601_DURATION_PARSER_HPP
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/qi_action.hpp>
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
template <typename Iterator> struct iso_8601_grammar : qi::grammar<Iterator>
|
||||
{
|
||||
iso_8601_grammar()
|
||||
: iso_8601_grammar::base_type(iso_period), temp(0), hours(0), minutes(0), seconds(0)
|
||||
{
|
||||
iso_period = qi::lit('P') >> qi::lit('T') >>
|
||||
((value >> hour >> value >> minute >> value >> second) |
|
||||
(value >> hour >> value >> minute) | (value >> hour >> value >> second) |
|
||||
(value >> hour) | (value >> minute >> value >> second) | (value >> minute) |
|
||||
(value >> second));
|
||||
|
||||
value = qi::uint_[boost::bind(&iso_8601_grammar<Iterator>::set_temp, this, ::_1)];
|
||||
second = (qi::lit('s') |
|
||||
qi::lit('S'))[boost::bind(&iso_8601_grammar<Iterator>::set_seconds, this)];
|
||||
minute = (qi::lit('m') |
|
||||
qi::lit('M'))[boost::bind(&iso_8601_grammar<Iterator>::set_minutes, this)];
|
||||
hour = (qi::lit('h') |
|
||||
qi::lit('H'))[boost::bind(&iso_8601_grammar<Iterator>::set_hours, this)];
|
||||
}
|
||||
|
||||
qi::rule<Iterator> iso_period;
|
||||
qi::rule<Iterator, std::string()> value, hour, minute, second;
|
||||
|
||||
unsigned temp;
|
||||
unsigned hours;
|
||||
unsigned minutes;
|
||||
unsigned seconds;
|
||||
|
||||
void set_temp(unsigned number) { temp = number; }
|
||||
|
||||
void set_hours()
|
||||
{
|
||||
if (temp < 24)
|
||||
{
|
||||
hours = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void set_minutes()
|
||||
{
|
||||
if (temp < 60)
|
||||
{
|
||||
minutes = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void set_seconds()
|
||||
{
|
||||
if (temp < 60)
|
||||
{
|
||||
seconds = temp;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_duration() const
|
||||
{
|
||||
unsigned temp = (3600 * hours + 60 * minutes + seconds);
|
||||
if (temp == 0)
|
||||
{
|
||||
temp = std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ISO_8601_DURATION_PARSER_HPP
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef JSON_LOGGER_HPP
|
||||
#define JSON_LOGGER_HPP
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace json
|
||||
{
|
||||
|
||||
// Used to append additional debugging information to the JSON response in a
|
||||
// thread safe manner.
|
||||
class Logger
|
||||
{
|
||||
using MapT = std::unordered_map<std::string, osrm::json::Value>;
|
||||
|
||||
public:
|
||||
static Logger* get()
|
||||
{
|
||||
static Logger logger;
|
||||
|
||||
bool return_logger = true;
|
||||
#ifdef NDEBUG
|
||||
return_logger = false;
|
||||
#endif
|
||||
#ifdef ENABLE_JSON_LOGGING
|
||||
return_logger = true;
|
||||
#endif
|
||||
|
||||
if (return_logger)
|
||||
{
|
||||
return &logger;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void initialize(const std::string& name)
|
||||
{
|
||||
if (!map.get())
|
||||
{
|
||||
map.reset(new MapT());
|
||||
}
|
||||
(*map)[name] = Object();
|
||||
}
|
||||
|
||||
void render(const std::string& name, Object& obj) const
|
||||
{
|
||||
obj.values["debug"] = map->at(name);
|
||||
}
|
||||
|
||||
boost::thread_specific_ptr<MapT> map;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* JSON_LOGGER_HPP */
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
// based on
|
||||
// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
|
||||
|
||||
#ifndef JSON_RENDERER_HPP
|
||||
#define JSON_RENDERER_HPP
|
||||
|
||||
#include "cast.hpp"
|
||||
#include "string_util.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace json
|
||||
{
|
||||
|
||||
struct Renderer : mapbox::util::static_visitor<>
|
||||
{
|
||||
explicit Renderer(std::ostream &_out) : out(_out) {}
|
||||
|
||||
void operator()(const String &string) const
|
||||
{
|
||||
out << "\"";
|
||||
out << escape_JSON(string.value);
|
||||
out << "\"";
|
||||
}
|
||||
|
||||
void operator()(const Number &number) const
|
||||
{
|
||||
out.precision(10);
|
||||
out << number.value;
|
||||
}
|
||||
|
||||
void operator()(const Object &object) const
|
||||
{
|
||||
out << "{";
|
||||
for (auto it = object.values.begin(), end = object.values.end(); it != end;)
|
||||
{
|
||||
out << "\"" << it->first << "\":";
|
||||
mapbox::util::apply_visitor(Renderer(out), it->second);
|
||||
if (++it != end)
|
||||
{
|
||||
out << ",";
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
}
|
||||
|
||||
void operator()(const Array &array) const
|
||||
{
|
||||
out << "[";
|
||||
for (auto it = array.values.cbegin(), end = array.values.cend(); it != end;)
|
||||
{
|
||||
mapbox::util::apply_visitor(Renderer(out), *it);
|
||||
if (++it != end)
|
||||
{
|
||||
out << ",";
|
||||
}
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
|
||||
void operator()(const True &) const { out << "true"; }
|
||||
|
||||
void operator()(const False &) const { out << "false"; }
|
||||
|
||||
void operator()(const Null &) const { out << "null"; }
|
||||
|
||||
private:
|
||||
std::ostream &out;
|
||||
};
|
||||
|
||||
struct ArrayRenderer : mapbox::util::static_visitor<>
|
||||
{
|
||||
explicit ArrayRenderer(std::vector<char> &_out) : out(_out) {}
|
||||
|
||||
void operator()(const String &string) const
|
||||
{
|
||||
out.push_back('\"');
|
||||
const auto string_to_insert = escape_JSON(string.value);
|
||||
out.insert(std::end(out), std::begin(string_to_insert), std::end(string_to_insert));
|
||||
out.push_back('\"');
|
||||
}
|
||||
|
||||
void operator()(const Number &number) const
|
||||
{
|
||||
const std::string number_string = cast::to_string_with_precision(number.value);
|
||||
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||
}
|
||||
|
||||
void operator()(const Object &object) const
|
||||
{
|
||||
out.push_back('{');
|
||||
for (auto it = object.values.begin(), end = object.values.end(); it != end;)
|
||||
{
|
||||
out.push_back('\"');
|
||||
out.insert(out.end(), it->first.begin(), it->first.end());
|
||||
out.push_back('\"');
|
||||
out.push_back(':');
|
||||
|
||||
mapbox::util::apply_visitor(ArrayRenderer(out), it->second);
|
||||
if (++it != end)
|
||||
{
|
||||
out.push_back(',');
|
||||
}
|
||||
}
|
||||
out.push_back('}');
|
||||
}
|
||||
|
||||
void operator()(const Array &array) const
|
||||
{
|
||||
out.push_back('[');
|
||||
for (auto it = array.values.cbegin(), end = array.values.cend(); it != end;)
|
||||
{
|
||||
mapbox::util::apply_visitor(ArrayRenderer(out), *it);
|
||||
if (++it != end)
|
||||
{
|
||||
out.push_back(',');
|
||||
}
|
||||
}
|
||||
out.push_back(']');
|
||||
}
|
||||
|
||||
void operator()(const True &) const
|
||||
{
|
||||
const std::string temp("true");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
void operator()(const False &) const
|
||||
{
|
||||
const std::string temp("false");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
void operator()(const Null &) const
|
||||
{
|
||||
const std::string temp("null");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char> &out;
|
||||
};
|
||||
|
||||
inline void render(std::ostream &out, const Object &object)
|
||||
{
|
||||
Value value = object;
|
||||
mapbox::util::apply_visitor(Renderer(out), value);
|
||||
}
|
||||
|
||||
inline void render(std::vector<char> &out, const Object &object)
|
||||
{
|
||||
Value value = object;
|
||||
mapbox::util::apply_visitor(ArrayRenderer(out), value);
|
||||
}
|
||||
|
||||
} // namespace json
|
||||
} // namespace osrm
|
||||
#endif // JSON_RENDERER_HPP
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef JSON_UTIL_HPP
|
||||
#define JSON_UTIL_HPP
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace json
|
||||
{
|
||||
|
||||
// Make sure we don't have inf and NaN values
|
||||
template <typename T> T clamp_float(T d)
|
||||
{
|
||||
if (std::isnan(d) || std::numeric_limits<T>::infinity() == d)
|
||||
{
|
||||
return std::numeric_limits<T>::max();
|
||||
}
|
||||
if (-std::numeric_limits<T>::infinity() == d)
|
||||
{
|
||||
return std::numeric_limits<T>::lowest();
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
template <typename... Args> osrm::json::Array make_array(Args... args)
|
||||
{
|
||||
osrm::json::Array a;
|
||||
append_to_container(a.values, args...);
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename T> osrm::json::Array make_array(const std::vector<T> &vector)
|
||||
{
|
||||
osrm::json::Array a;
|
||||
for (const auto &v : vector)
|
||||
{
|
||||
a.values.emplace_back(v);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// template specialization needed as clang does not play nice
|
||||
template <> osrm::json::Array make_array(const std::vector<bool> &vector)
|
||||
{
|
||||
osrm::json::Array a;
|
||||
for (const bool v : vector)
|
||||
{
|
||||
a.values.emplace_back(v);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// Easy acces to object hierachies
|
||||
osrm::json::Value &get(osrm::json::Value &value) { return value; }
|
||||
|
||||
template <typename... Keys>
|
||||
osrm::json::Value &get(osrm::json::Value &value, const char *key, Keys... keys)
|
||||
{
|
||||
using recursive_object_t = mapbox::util::recursive_wrapper<osrm::json::Object>;
|
||||
return get(value.get<recursive_object_t>().get().values[key], keys...);
|
||||
}
|
||||
|
||||
template <typename... Keys>
|
||||
osrm::json::Value &get(osrm::json::Value &value, unsigned key, Keys... keys)
|
||||
{
|
||||
using recursive_array_t = mapbox::util::recursive_wrapper<osrm::json::Array>;
|
||||
return get(value.get<recursive_array_t>().get().values[key], keys...);
|
||||
}
|
||||
|
||||
} // namespace json
|
||||
} // namespace osrm
|
||||
#endif // JSON_UTIL_HPP
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef LUA_UTIL_HPP
|
||||
#define LUA_UTIL_HPP
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
}
|
||||
|
||||
#include <boost/filesystem/convenience.hpp>
|
||||
#include <luabind/luabind.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
template <typename T> void LUA_print(T output) { std::cout << "[LUA] " << output << std::endl; }
|
||||
|
||||
// Check if the lua function <name> is defined
|
||||
inline bool lua_function_exists(lua_State *lua_state, const char *name)
|
||||
{
|
||||
luabind::object globals_table = luabind::globals(lua_state);
|
||||
luabind::object lua_function = globals_table[name];
|
||||
return lua_function && (luabind::type(lua_function) == LUA_TFUNCTION);
|
||||
}
|
||||
|
||||
// Add the folder contain the script to the lua load path, so script can easily require() other lua
|
||||
// scripts inside that folder, or subfolders.
|
||||
// See http://lua-users.org/wiki/PackagePath for details on the package.path syntax.
|
||||
inline void luaAddScriptFolderToLoadPath(lua_State *lua_state, const char *file_name)
|
||||
{
|
||||
boost::filesystem::path profile_path = boost::filesystem::canonical(file_name);
|
||||
std::string folder = profile_path.parent_path().string();
|
||||
// TODO: This code is most probably not Windows safe since it uses UNIX'ish path delimiters
|
||||
const std::string lua_code = "package.path = \"" + folder + "/?.lua;\" .. package.path";
|
||||
luaL_dostring(lua_state, lua_code.c_str());
|
||||
}
|
||||
|
||||
#endif // LUA_UTIL_HPP
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MAKE_UNIQUE_H_
|
||||
#define MAKE_UNIQUE_H_
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
// Implement make_unique according to N3656. Taken from libcxx's implementation
|
||||
|
||||
/// \brief Constructs a `new T()` with the given args and returns a
|
||||
/// `unique_ptr<T>` which owns the object.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// auto p = make_unique<int>();
|
||||
/// auto p = make_unique<std::tuple<int, int>>(0, 1);
|
||||
template <class T, class... Args>
|
||||
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
|
||||
make_unique(Args &&... args)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/// \brief Constructs a `new T[n]` with the given args and returns a
|
||||
/// `unique_ptr<T[]>` which owns the object.
|
||||
///
|
||||
/// \param n size of the new array.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// auto p = make_unique<int[]>(2); // value-initializes the array with 0's.
|
||||
template <class T>
|
||||
typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0,
|
||||
std::unique_ptr<T>>::type
|
||||
make_unique(size_t n)
|
||||
{
|
||||
return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
|
||||
}
|
||||
|
||||
/// This function isn't used and is only here to provide better compile errors.
|
||||
template <class T, class... Args>
|
||||
typename std::enable_if<std::extent<T>::value != 0>::type make_unique(Args &&...) = delete;
|
||||
}
|
||||
#endif // MAKE_UNIQUE_H_
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MATCHING_DEBUG_INFO_HPP
|
||||
#define MATCHING_DEBUG_INFO_HPP
|
||||
|
||||
#include "json_logger.hpp"
|
||||
#include "json_util.hpp"
|
||||
#include "../data_structures/hidden_markov_model.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
// Provides the debug interface for introspection tools
|
||||
struct MatchingDebugInfo
|
||||
{
|
||||
MatchingDebugInfo(const osrm::json::Logger *logger) : logger(logger)
|
||||
{
|
||||
if (logger)
|
||||
{
|
||||
object = &logger->map->at("matching");
|
||||
}
|
||||
}
|
||||
|
||||
template <class CandidateLists> void initialize(const CandidateLists &candidates_list)
|
||||
{
|
||||
// json logger not enabled
|
||||
if (!logger)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
osrm::json::Array states;
|
||||
for (auto &elem : candidates_list)
|
||||
{
|
||||
osrm::json::Array timestamps;
|
||||
for (auto &elem_s : elem)
|
||||
{
|
||||
osrm::json::Object state;
|
||||
state.values["transitions"] = osrm::json::Array();
|
||||
state.values["coordinate"] =
|
||||
osrm::json::make_array(elem_s.phantom_node.location.lat / COORDINATE_PRECISION,
|
||||
elem_s.phantom_node.location.lon / COORDINATE_PRECISION);
|
||||
state.values["viterbi"] =
|
||||
osrm::json::clamp_float(osrm::matching::IMPOSSIBLE_LOG_PROB);
|
||||
state.values["pruned"] = 0u;
|
||||
timestamps.values.push_back(state);
|
||||
}
|
||||
states.values.push_back(timestamps);
|
||||
}
|
||||
osrm::json::get(*object, "states") = states;
|
||||
}
|
||||
|
||||
void add_transition_info(const unsigned prev_t,
|
||||
const unsigned current_t,
|
||||
const unsigned prev_state,
|
||||
const unsigned current_state,
|
||||
const double prev_viterbi,
|
||||
const double emission_pr,
|
||||
const double transition_pr,
|
||||
const double network_distance,
|
||||
const double haversine_distance)
|
||||
{
|
||||
// json logger not enabled
|
||||
if (!logger)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
osrm::json::Object transistion;
|
||||
transistion.values["to"] = osrm::json::make_array(current_t, current_state);
|
||||
transistion.values["properties"] = osrm::json::make_array(
|
||||
osrm::json::clamp_float(prev_viterbi), osrm::json::clamp_float(emission_pr),
|
||||
osrm::json::clamp_float(transition_pr), network_distance, haversine_distance);
|
||||
|
||||
osrm::json::get(*object, "states", prev_t, prev_state, "transitions")
|
||||
.get<mapbox::util::recursive_wrapper<osrm::json::Array>>()
|
||||
.get()
|
||||
.values.push_back(transistion);
|
||||
}
|
||||
|
||||
void set_viterbi(const std::vector<std::vector<double>> &viterbi,
|
||||
const std::vector<std::vector<bool>> &pruned,
|
||||
const std::vector<std::vector<bool>> &suspicious)
|
||||
{
|
||||
// json logger not enabled
|
||||
if (!logger)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto t = 0u; t < viterbi.size(); t++)
|
||||
{
|
||||
for (auto s_prime = 0u; s_prime < viterbi[t].size(); ++s_prime)
|
||||
{
|
||||
osrm::json::get(*object, "states", t, s_prime, "viterbi") =
|
||||
osrm::json::clamp_float(viterbi[t][s_prime]);
|
||||
osrm::json::get(*object, "states", t, s_prime, "pruned") =
|
||||
static_cast<unsigned>(pruned[t][s_prime]);
|
||||
osrm::json::get(*object, "states", t, s_prime, "suspicious") =
|
||||
static_cast<unsigned>(suspicious[t][s_prime]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_chosen(const unsigned t, const unsigned s)
|
||||
{
|
||||
// json logger not enabled
|
||||
if (!logger)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
osrm::json::get(*object, "states", t, s, "chosen") = true;
|
||||
}
|
||||
|
||||
void add_breakage(const std::vector<bool> &breakage)
|
||||
{
|
||||
// json logger not enabled
|
||||
if (!logger)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
osrm::json::get(*object, "breakage") = osrm::json::make_array(breakage);
|
||||
}
|
||||
|
||||
const osrm::json::Logger *logger;
|
||||
osrm::json::Value *object;
|
||||
};
|
||||
|
||||
#endif // MATCHING_DEBUG_INFO_HPP
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MATRIX_GRAPH_WRAPPER_H
|
||||
#define MATRIX_GRAPH_WRAPPER_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
// This Wrapper provides all methods that are needed for TarjanSCC, when the graph is given in a
|
||||
// matrix representation (e.g. as output from a distance table call)
|
||||
|
||||
template <typename T> class MatrixGraphWrapper
|
||||
{
|
||||
public:
|
||||
MatrixGraphWrapper(std::vector<T> table, const std::size_t number_of_nodes)
|
||||
: table_(std::move(table)), number_of_nodes_(number_of_nodes){};
|
||||
|
||||
std::size_t GetNumberOfNodes() const { return number_of_nodes_; }
|
||||
|
||||
std::vector<T> GetAdjacentEdgeRange(const NodeID node) const
|
||||
{
|
||||
|
||||
std::vector<T> edges;
|
||||
// find all valid adjacent edges and move to vector `edges`
|
||||
for (std::size_t i = 0; i < number_of_nodes_; ++i)
|
||||
{
|
||||
if (*(std::begin(table_) + node * number_of_nodes_ + i) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges.push_back(i);
|
||||
}
|
||||
}
|
||||
return edges;
|
||||
}
|
||||
|
||||
EdgeWeight GetTarget(const EdgeWeight edge) const { return edge; }
|
||||
|
||||
private:
|
||||
const std::vector<T> table_;
|
||||
const std::size_t number_of_nodes_;
|
||||
};
|
||||
|
||||
#endif // MATRIX_GRAPH_WRAPPER_H
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MERCATOR_HPP
|
||||
#define MERCATOR_HPP
|
||||
|
||||
struct mercator
|
||||
{
|
||||
static double y2lat(const double value) noexcept;
|
||||
|
||||
static double lat2y(const double latitude) noexcept;
|
||||
};
|
||||
|
||||
#endif // MERCATOR_HPP
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef NODE_BASED_GRAPH_HPP
|
||||
#define NODE_BASED_GRAPH_HPP
|
||||
|
||||
#include "dynamic_graph.hpp"
|
||||
#include "import_edge.hpp"
|
||||
#include "../util/graph_utils.hpp"
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct NodeBasedEdgeData
|
||||
{
|
||||
NodeBasedEdgeData()
|
||||
: distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID),
|
||||
name_id(std::numeric_limits<unsigned>::max()), access_restricted(false),
|
||||
reversed(false), roundabout(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
NodeBasedEdgeData(int distance, unsigned edge_id, unsigned name_id,
|
||||
bool access_restricted, bool reversed,
|
||||
bool roundabout, bool startpoint, TravelMode travel_mode)
|
||||
: distance(distance), edge_id(edge_id), name_id(name_id),
|
||||
access_restricted(access_restricted), reversed(reversed),
|
||||
roundabout(roundabout), startpoint(startpoint), travel_mode(travel_mode)
|
||||
{
|
||||
}
|
||||
|
||||
int distance;
|
||||
unsigned edge_id;
|
||||
unsigned name_id;
|
||||
bool access_restricted : 1;
|
||||
bool reversed : 1;
|
||||
bool roundabout : 1;
|
||||
bool startpoint : 1;
|
||||
TravelMode travel_mode : 4;
|
||||
|
||||
bool IsCompatibleTo(const NodeBasedEdgeData &other) const
|
||||
{
|
||||
return (reversed == other.reversed) && (name_id == other.name_id) &&
|
||||
(travel_mode == other.travel_mode);
|
||||
}
|
||||
};
|
||||
|
||||
using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
|
||||
|
||||
/// Factory method to create NodeBasedDynamicGraph from NodeBasedEdges
|
||||
/// Since DynamicGraph expects directed edges, we need to insert
|
||||
/// two edges for undirected edges.
|
||||
inline std::shared_ptr<NodeBasedDynamicGraph>
|
||||
NodeBasedDynamicGraphFromEdges(std::size_t number_of_nodes, const std::vector<NodeBasedEdge> &input_edge_list)
|
||||
{
|
||||
auto edges_list = directedEdgesFromCompressed<NodeBasedDynamicGraph::InputEdge>(input_edge_list,
|
||||
[](NodeBasedDynamicGraph::InputEdge& output_edge, const NodeBasedEdge& input_edge)
|
||||
{
|
||||
output_edge.data.distance = static_cast<int>(input_edge.weight);
|
||||
BOOST_ASSERT(output_edge.data.distance > 0);
|
||||
|
||||
output_edge.data.roundabout = input_edge.roundabout;
|
||||
output_edge.data.name_id = input_edge.name_id;
|
||||
output_edge.data.access_restricted = input_edge.access_restricted;
|
||||
output_edge.data.travel_mode = input_edge.travel_mode;
|
||||
output_edge.data.startpoint = input_edge.startpoint;
|
||||
}
|
||||
);
|
||||
|
||||
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
||||
|
||||
auto graph = std::make_shared<NodeBasedDynamicGraph>(
|
||||
static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
#endif // NODE_BASED_GRAPH_HPP
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef OSRM_EXCEPTION_HPP
|
||||
#define OSRM_EXCEPTION_HPP
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
class exception final : public std::exception
|
||||
{
|
||||
public:
|
||||
explicit exception(const char *message) : message(message) {}
|
||||
explicit exception(std::string message) : message(std::move(message)) {}
|
||||
|
||||
private:
|
||||
// This function exists to 'anchor' the class, and stop the compiler from
|
||||
// copying vtable and RTTI info into every object file that includes
|
||||
// this header. (Caught by -Wweak-vtables under Clang.)
|
||||
virtual void anchor() const;
|
||||
const char *what() const noexcept override { return message.c_str(); }
|
||||
const std::string message;
|
||||
};
|
||||
}
|
||||
#endif /* OSRM_EXCEPTION_HPP */
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PERCENT_HPP
|
||||
#define PERCENT_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <atomic>
|
||||
|
||||
class Percent
|
||||
{
|
||||
public:
|
||||
explicit Percent(unsigned max_value, unsigned step = 5) { reinit(max_value, step); }
|
||||
|
||||
// Reinitializes
|
||||
void reinit(unsigned max_value, unsigned step = 5)
|
||||
{
|
||||
m_max_value = max_value;
|
||||
m_current_value = 0;
|
||||
m_percent_interval = m_max_value / 100;
|
||||
m_next_threshold = m_percent_interval;
|
||||
m_last_percent = 0;
|
||||
m_step = step;
|
||||
}
|
||||
|
||||
// If there has been significant progress, display it.
|
||||
void printStatus(unsigned current_value)
|
||||
{
|
||||
if (current_value >= m_next_threshold)
|
||||
{
|
||||
m_next_threshold += m_percent_interval;
|
||||
printPercent(current_value / static_cast<double>(m_max_value) * 100.);
|
||||
}
|
||||
if (current_value + 1 == m_max_value)
|
||||
std::cout << " 100%" << std::endl;
|
||||
}
|
||||
|
||||
void printIncrement()
|
||||
{
|
||||
++m_current_value;
|
||||
printStatus(m_current_value);
|
||||
}
|
||||
|
||||
void printAddition(const unsigned addition)
|
||||
{
|
||||
m_current_value += addition;
|
||||
printStatus(m_current_value);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic_uint m_current_value;
|
||||
unsigned m_max_value;
|
||||
unsigned m_percent_interval;
|
||||
unsigned m_next_threshold;
|
||||
unsigned m_last_percent;
|
||||
unsigned m_step;
|
||||
|
||||
// Displays progress.
|
||||
void printPercent(double percent)
|
||||
{
|
||||
while (percent >= m_last_percent + m_step)
|
||||
{
|
||||
m_last_percent += m_step;
|
||||
if (m_last_percent % 10 == 0)
|
||||
{
|
||||
std::cout << " " << m_last_percent << "% ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << ".";
|
||||
}
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PERCENT_HPP
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RANGE_ALGORITHMS_HPP
|
||||
#define RANGE_ALGORITHMS_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
template <class Container>
|
||||
auto max_element(const Container &c) -> decltype(std::max_element(c.begin(), c.end()))
|
||||
{
|
||||
return std::max_element(c.begin(), c.end());
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
auto max_element(const Container &c) -> decltype(std::max_element(c.cbegin(), c.cend()))
|
||||
{
|
||||
return std::max_element(c.cbegin(), c.cend());
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RANGE_ALGORITHMS_HPP
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RANGE_TABLE_HPP
|
||||
#define RANGE_TABLE_HPP
|
||||
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "shared_memory_factory.hpp"
|
||||
#include "shared_memory_vector_wrapper.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <array>
|
||||
/*
|
||||
* These pre-declarations are needed because parsing C++ is hard
|
||||
* and otherwise the compiler gets confused.
|
||||
*/
|
||||
|
||||
template <unsigned BLOCK_SIZE = 16, bool USE_SHARED_MEMORY = false> class RangeTable;
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
|
||||
/**
|
||||
* Stores adjacent ranges in a compressed format.
|
||||
*
|
||||
* Maximum supported length of a range is 255.
|
||||
*
|
||||
* Note: BLOCK_SIZE is the number of differential encodoed values.
|
||||
* But each block consists of an absolute value and BLOCK_SIZE differential values.
|
||||
* So the effective block size is sizeof(unsigned) + BLOCK_SIZE.
|
||||
*/
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
{
|
||||
public:
|
||||
using BlockT = std::array<unsigned char, BLOCK_SIZE>;
|
||||
using BlockContainerT = typename ShM<BlockT, USE_SHARED_MEMORY>::vector;
|
||||
using OffsetContainerT = typename ShM<unsigned, USE_SHARED_MEMORY>::vector;
|
||||
using RangeT = osrm::range<unsigned>;
|
||||
|
||||
friend std::ostream &operator<<<>(std::ostream &out, const RangeTable &table);
|
||||
friend std::istream &operator>><>(std::istream &in, RangeTable &table);
|
||||
|
||||
RangeTable() : sum_lengths(0) {}
|
||||
|
||||
// for loading from shared memory
|
||||
explicit RangeTable(OffsetContainerT &external_offsets,
|
||||
BlockContainerT &external_blocks,
|
||||
const unsigned sum_lengths)
|
||||
: sum_lengths(sum_lengths)
|
||||
{
|
||||
block_offsets.swap(external_offsets);
|
||||
diff_blocks.swap(external_blocks);
|
||||
}
|
||||
|
||||
// construct table from length vector
|
||||
template<typename VectorT>
|
||||
explicit RangeTable(const VectorT &lengths)
|
||||
{
|
||||
const unsigned number_of_blocks = [&lengths]()
|
||||
{
|
||||
unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1);
|
||||
if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0)
|
||||
{
|
||||
num += 1;
|
||||
}
|
||||
return num;
|
||||
}();
|
||||
|
||||
block_offsets.reserve(number_of_blocks);
|
||||
diff_blocks.reserve(number_of_blocks);
|
||||
|
||||
unsigned last_length = 0;
|
||||
unsigned lengths_prefix_sum = 0;
|
||||
unsigned block_idx = 0;
|
||||
unsigned block_counter = 0;
|
||||
BlockT block;
|
||||
unsigned block_sum = 0;
|
||||
for (const unsigned l : lengths)
|
||||
{
|
||||
// first entry of a block: encode absolute offset
|
||||
if (block_idx == 0)
|
||||
{
|
||||
block_offsets.push_back(lengths_prefix_sum);
|
||||
block_sum = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
block[block_idx - 1] = last_length;
|
||||
block_sum += last_length;
|
||||
}
|
||||
|
||||
BOOST_ASSERT((block_idx == 0 && block_offsets[block_counter] == lengths_prefix_sum) ||
|
||||
lengths_prefix_sum == (block_offsets[block_counter] + block_sum));
|
||||
|
||||
// block is full
|
||||
if (BLOCK_SIZE == block_idx)
|
||||
{
|
||||
diff_blocks.push_back(block);
|
||||
block_counter++;
|
||||
}
|
||||
|
||||
// we can only store strings with length 255
|
||||
BOOST_ASSERT(l <= 255);
|
||||
|
||||
lengths_prefix_sum += l;
|
||||
last_length = l;
|
||||
|
||||
block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
|
||||
}
|
||||
|
||||
// Last block can't be finished because we didn't add the sentinel
|
||||
BOOST_ASSERT(block_counter == (number_of_blocks - 1));
|
||||
|
||||
// one block missing: starts with guard value
|
||||
if (0 == block_idx)
|
||||
{
|
||||
// the last value is used as sentinel
|
||||
block_offsets.push_back(lengths_prefix_sum);
|
||||
block_idx = 1;
|
||||
last_length = 0;
|
||||
}
|
||||
|
||||
while (0 != block_idx)
|
||||
{
|
||||
block[block_idx - 1] = last_length;
|
||||
last_length = 0;
|
||||
block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
|
||||
}
|
||||
diff_blocks.push_back(block);
|
||||
|
||||
BOOST_ASSERT(diff_blocks.size() == number_of_blocks &&
|
||||
block_offsets.size() == number_of_blocks);
|
||||
|
||||
sum_lengths = lengths_prefix_sum;
|
||||
}
|
||||
|
||||
inline RangeT GetRange(const unsigned id) const
|
||||
{
|
||||
BOOST_ASSERT(id < block_offsets.size() + diff_blocks.size() * BLOCK_SIZE);
|
||||
// internal_idx 0 is implicitly stored in block_offsets[block_idx]
|
||||
const unsigned internal_idx = id % (BLOCK_SIZE + 1);
|
||||
const unsigned block_idx = id / (BLOCK_SIZE + 1);
|
||||
|
||||
BOOST_ASSERT(block_idx < diff_blocks.size());
|
||||
|
||||
unsigned begin_idx = 0;
|
||||
unsigned end_idx = 0;
|
||||
begin_idx = block_offsets[block_idx];
|
||||
const BlockT &block = diff_blocks[block_idx];
|
||||
if (internal_idx > 0)
|
||||
{
|
||||
begin_idx += PrefixSumAtIndex(internal_idx - 1, block);
|
||||
}
|
||||
|
||||
// next index inside current block
|
||||
if (internal_idx < BLOCK_SIZE)
|
||||
{
|
||||
// note internal_idx - 1 is the *current* index for uint8_blocks
|
||||
end_idx = begin_idx + block[internal_idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(block_idx < block_offsets.size() - 1);
|
||||
end_idx = block_offsets[block_idx + 1];
|
||||
}
|
||||
|
||||
BOOST_ASSERT(begin_idx < sum_lengths && end_idx <= sum_lengths);
|
||||
BOOST_ASSERT(begin_idx <= end_idx);
|
||||
|
||||
return osrm::irange(begin_idx, end_idx);
|
||||
}
|
||||
|
||||
private:
|
||||
inline unsigned PrefixSumAtIndex(int index, const BlockT &block) const;
|
||||
|
||||
// contains offset for each differential block
|
||||
OffsetContainerT block_offsets;
|
||||
// blocks of differential encoded offsets, should be aligned
|
||||
BlockContainerT diff_blocks;
|
||||
unsigned sum_lengths;
|
||||
};
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index,
|
||||
const BlockT &block) const
|
||||
{
|
||||
// this loop looks inefficent, but a modern compiler
|
||||
// will emit nice SIMD here, at least for sensible block sizes. (I checked.)
|
||||
unsigned sum = 0;
|
||||
for (int i = 0; i <= index; ++i)
|
||||
{
|
||||
sum += block[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
{
|
||||
// write number of block
|
||||
const unsigned number_of_blocks = table.diff_blocks.size();
|
||||
out.write((char *)&number_of_blocks, sizeof(unsigned));
|
||||
// write total length
|
||||
out.write((char *)&table.sum_lengths, sizeof(unsigned));
|
||||
// write block offsets
|
||||
out.write((char *)table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size());
|
||||
// write blocks
|
||||
out.write((char *)table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size());
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
{
|
||||
// read number of block
|
||||
unsigned number_of_blocks;
|
||||
in.read((char *)&number_of_blocks, sizeof(unsigned));
|
||||
// read total length
|
||||
in.read((char *)&table.sum_lengths, sizeof(unsigned));
|
||||
|
||||
table.block_offsets.resize(number_of_blocks);
|
||||
table.diff_blocks.resize(number_of_blocks);
|
||||
|
||||
// read block offsets
|
||||
in.read((char *)table.block_offsets.data(), sizeof(unsigned) * number_of_blocks);
|
||||
// read blocks
|
||||
in.read((char *)table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks);
|
||||
return in;
|
||||
}
|
||||
|
||||
#endif // RANGE_TABLE_HPP
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RECTANGLE_HPP
|
||||
#define RECTANGLE_HPP
|
||||
|
||||
#include "../algorithms/coordinate_calculation.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
// TODO: Make template type, add tests
|
||||
struct RectangleInt2D
|
||||
{
|
||||
RectangleInt2D()
|
||||
: min_lon(std::numeric_limits<int32_t>::max()),
|
||||
max_lon(std::numeric_limits<int32_t>::min()),
|
||||
min_lat(std::numeric_limits<int32_t>::max()), max_lat(std::numeric_limits<int32_t>::min())
|
||||
{
|
||||
}
|
||||
|
||||
int32_t min_lon, max_lon;
|
||||
int32_t min_lat, max_lat;
|
||||
|
||||
void MergeBoundingBoxes(const RectangleInt2D &other)
|
||||
{
|
||||
min_lon = std::min(min_lon, other.min_lon);
|
||||
max_lon = std::max(max_lon, other.max_lon);
|
||||
min_lat = std::min(min_lat, other.min_lat);
|
||||
max_lat = std::max(max_lat, other.max_lat);
|
||||
BOOST_ASSERT(min_lat != std::numeric_limits<int32_t>::min());
|
||||
BOOST_ASSERT(min_lon != std::numeric_limits<int32_t>::min());
|
||||
BOOST_ASSERT(max_lat != std::numeric_limits<int32_t>::min());
|
||||
BOOST_ASSERT(max_lon != std::numeric_limits<int32_t>::min());
|
||||
}
|
||||
|
||||
FixedPointCoordinate Centroid() const
|
||||
{
|
||||
FixedPointCoordinate centroid;
|
||||
// The coordinates of the midpoints are given by:
|
||||
// x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||
centroid.lon = (min_lon + max_lon) / 2;
|
||||
centroid.lat = (min_lat + max_lat) / 2;
|
||||
return centroid;
|
||||
}
|
||||
|
||||
bool Intersects(const RectangleInt2D &other) const
|
||||
{
|
||||
FixedPointCoordinate upper_left(other.max_lat, other.min_lon);
|
||||
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
|
||||
FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
|
||||
FixedPointCoordinate lower_left(other.min_lat, other.min_lon);
|
||||
|
||||
return (Contains(upper_left) || Contains(upper_right) || Contains(lower_right) ||
|
||||
Contains(lower_left));
|
||||
}
|
||||
|
||||
float GetMinDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
const bool is_contained = Contains(location);
|
||||
if (is_contained)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
enum Direction
|
||||
{
|
||||
INVALID = 0,
|
||||
NORTH = 1,
|
||||
SOUTH = 2,
|
||||
EAST = 4,
|
||||
NORTH_EAST = 5,
|
||||
SOUTH_EAST = 6,
|
||||
WEST = 8,
|
||||
NORTH_WEST = 9,
|
||||
SOUTH_WEST = 10
|
||||
};
|
||||
|
||||
Direction d = INVALID;
|
||||
if (location.lat > max_lat)
|
||||
d = (Direction)(d | NORTH);
|
||||
else if (location.lat < min_lat)
|
||||
d = (Direction)(d | SOUTH);
|
||||
if (location.lon > max_lon)
|
||||
d = (Direction)(d | EAST);
|
||||
else if (location.lon < min_lon)
|
||||
d = (Direction)(d | WEST);
|
||||
|
||||
BOOST_ASSERT(d != INVALID);
|
||||
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
switch (d)
|
||||
{
|
||||
case NORTH:
|
||||
min_dist = coordinate_calculation::great_circle_distance(
|
||||
location, FixedPointCoordinate(max_lat, location.lon));
|
||||
break;
|
||||
case SOUTH:
|
||||
min_dist = coordinate_calculation::great_circle_distance(
|
||||
location, FixedPointCoordinate(min_lat, location.lon));
|
||||
break;
|
||||
case WEST:
|
||||
min_dist = coordinate_calculation::great_circle_distance(
|
||||
location, FixedPointCoordinate(location.lat, min_lon));
|
||||
break;
|
||||
case EAST:
|
||||
min_dist = coordinate_calculation::great_circle_distance(
|
||||
location, FixedPointCoordinate(location.lat, max_lon));
|
||||
break;
|
||||
case NORTH_EAST:
|
||||
min_dist = coordinate_calculation::great_circle_distance(
|
||||
location, FixedPointCoordinate(max_lat, max_lon));
|
||||
break;
|
||||
case NORTH_WEST:
|
||||
min_dist = coordinate_calculation::great_circle_distance(
|
||||
location, FixedPointCoordinate(max_lat, min_lon));
|
||||
break;
|
||||
case SOUTH_EAST:
|
||||
min_dist = coordinate_calculation::great_circle_distance(
|
||||
location, FixedPointCoordinate(min_lat, max_lon));
|
||||
break;
|
||||
case SOUTH_WEST:
|
||||
min_dist = coordinate_calculation::great_circle_distance(
|
||||
location, FixedPointCoordinate(min_lat, min_lon));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(min_dist < std::numeric_limits<float>::max());
|
||||
|
||||
return min_dist;
|
||||
}
|
||||
|
||||
float GetMinMaxDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
float min_max_dist = std::numeric_limits<float>::max();
|
||||
// Get minmax distance to each of the four sides
|
||||
const FixedPointCoordinate upper_left(max_lat, min_lon);
|
||||
const FixedPointCoordinate upper_right(max_lat, max_lon);
|
||||
const FixedPointCoordinate lower_right(min_lat, max_lon);
|
||||
const FixedPointCoordinate lower_left(min_lat, min_lon);
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(coordinate_calculation::great_circle_distance(location, upper_left),
|
||||
coordinate_calculation::great_circle_distance(location, upper_right)));
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(coordinate_calculation::great_circle_distance(location, upper_right),
|
||||
coordinate_calculation::great_circle_distance(location, lower_right)));
|
||||
|
||||
min_max_dist =
|
||||
std::min(min_max_dist,
|
||||
std::max(coordinate_calculation::great_circle_distance(location, lower_right),
|
||||
coordinate_calculation::great_circle_distance(location, lower_left)));
|
||||
|
||||
min_max_dist =
|
||||
std::min(min_max_dist,
|
||||
std::max(coordinate_calculation::great_circle_distance(location, lower_left),
|
||||
coordinate_calculation::great_circle_distance(location, upper_left)));
|
||||
return min_max_dist;
|
||||
}
|
||||
|
||||
bool Contains(const FixedPointCoordinate &location) const
|
||||
{
|
||||
const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat);
|
||||
const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon);
|
||||
return lats_contained && lons_contained;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ROUTED_OPTIONS_HPP
|
||||
#define ROUTED_OPTIONS_HPP
|
||||
|
||||
#include "util/version.hpp"
|
||||
#include "ini_file.hpp"
|
||||
#include "osrm_exception.hpp"
|
||||
#include "simple_logger.hpp"
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
const static unsigned INIT_OK_START_ENGINE = 0;
|
||||
const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
|
||||
const static unsigned INIT_FAILED = -1;
|
||||
|
||||
inline void
|
||||
populate_base_path(std::unordered_map<std::string, boost::filesystem::path> &server_paths)
|
||||
{
|
||||
// populate the server_path object
|
||||
auto path_iterator = server_paths.find("base");
|
||||
|
||||
// if a base path has been set, we populate it.
|
||||
if (path_iterator != server_paths.end())
|
||||
{
|
||||
const std::string base_string = path_iterator->second.string();
|
||||
SimpleLogger().Write() << "populating base path: " << base_string;
|
||||
|
||||
server_paths["hsgrdata"] = base_string + ".hsgr";
|
||||
BOOST_ASSERT(server_paths.find("hsgrdata") != server_paths.end());
|
||||
server_paths["nodesdata"] = base_string + ".nodes";
|
||||
BOOST_ASSERT(server_paths.find("nodesdata") != server_paths.end());
|
||||
server_paths["coredata"] = base_string + ".core";
|
||||
BOOST_ASSERT(server_paths.find("coredata") != server_paths.end());
|
||||
server_paths["edgesdata"] = base_string + ".edges";
|
||||
BOOST_ASSERT(server_paths.find("edgesdata") != server_paths.end());
|
||||
server_paths["geometries"] = base_string + ".geometry";
|
||||
BOOST_ASSERT(server_paths.find("geometries") != server_paths.end());
|
||||
server_paths["ramindex"] = base_string + ".ramIndex";
|
||||
BOOST_ASSERT(server_paths.find("ramindex") != server_paths.end());
|
||||
server_paths["fileindex"] = base_string + ".fileIndex";
|
||||
BOOST_ASSERT(server_paths.find("fileindex") != server_paths.end());
|
||||
server_paths["namesdata"] = base_string + ".names";
|
||||
BOOST_ASSERT(server_paths.find("namesdata") != server_paths.end());
|
||||
server_paths["timestamp"] = base_string + ".timestamp";
|
||||
BOOST_ASSERT(server_paths.find("timestamp") != server_paths.end());
|
||||
}
|
||||
|
||||
// check if files are give and whether they exist at all
|
||||
path_iterator = server_paths.find("hsgrdata");
|
||||
if (path_iterator == server_paths.end() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception(".hsgr not found");
|
||||
}
|
||||
|
||||
path_iterator = server_paths.find("nodesdata");
|
||||
if (path_iterator == server_paths.end() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception(".nodes not found");
|
||||
}
|
||||
|
||||
path_iterator = server_paths.find("edgesdata");
|
||||
if (path_iterator == server_paths.end() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception(".edges not found");
|
||||
}
|
||||
|
||||
path_iterator = server_paths.find("geometries");
|
||||
if (path_iterator == server_paths.end() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception(".geometry not found");
|
||||
}
|
||||
|
||||
path_iterator = server_paths.find("ramindex");
|
||||
if (path_iterator == server_paths.end() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception(".ramIndex not found");
|
||||
}
|
||||
|
||||
path_iterator = server_paths.find("fileindex");
|
||||
if (path_iterator == server_paths.end() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception(".fileIndex not found");
|
||||
}
|
||||
|
||||
path_iterator = server_paths.find("namesdata");
|
||||
if (path_iterator == server_paths.end() ||
|
||||
!boost::filesystem::is_regular_file(path_iterator->second))
|
||||
{
|
||||
throw osrm::exception(".namesIndex not found");
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "HSGR file:\t" << server_paths["hsgrdata"];
|
||||
SimpleLogger().Write(logDEBUG) << "Nodes file:\t" << server_paths["nodesdata"];
|
||||
SimpleLogger().Write(logDEBUG) << "Edges file:\t" << server_paths["edgesdata"];
|
||||
SimpleLogger().Write(logDEBUG) << "Geometry file:\t" << server_paths["geometries"];
|
||||
SimpleLogger().Write(logDEBUG) << "RAM file:\t" << server_paths["ramindex"];
|
||||
SimpleLogger().Write(logDEBUG) << "Index file:\t" << server_paths["fileindex"];
|
||||
SimpleLogger().Write(logDEBUG) << "Names file:\t" << server_paths["namesdata"];
|
||||
SimpleLogger().Write(logDEBUG) << "Timestamp file:\t" << server_paths["timestamp"];
|
||||
}
|
||||
|
||||
// generate boost::program_options object for the routing part
|
||||
inline unsigned
|
||||
GenerateServerProgramOptions(const int argc,
|
||||
const char *argv[],
|
||||
std::unordered_map<std::string, boost::filesystem::path> &paths,
|
||||
std::string &ip_address,
|
||||
int &ip_port,
|
||||
int &requested_num_threads,
|
||||
bool &use_shared_memory,
|
||||
bool &trial,
|
||||
int &max_locations_trip,
|
||||
int &max_locations_viaroute,
|
||||
int &max_locations_distance_table,
|
||||
int &max_locations_map_matching)
|
||||
{
|
||||
using boost::program_options::value;
|
||||
using boost::filesystem::path;
|
||||
|
||||
// declare a group of options that will be allowed only on command line
|
||||
boost::program_options::options_description generic_options("Options");
|
||||
generic_options.add_options() //
|
||||
("version,v", "Show version")("help,h", "Show this help message") //
|
||||
("config,c", value<boost::filesystem::path>(&paths["config"])->default_value("server.ini"),
|
||||
"Path to a configuration file") //
|
||||
("trial", value<bool>(&trial)->implicit_value(true), "Quit after initialization");
|
||||
|
||||
// declare a group of options that will be allowed both on command line
|
||||
// as well as in a config file
|
||||
boost::program_options::options_description config_options("Configuration");
|
||||
config_options.add_options() //
|
||||
("hsgrdata", value<boost::filesystem::path>(&paths["hsgrdata"]), ".hsgr file") //
|
||||
("nodesdata", value<boost::filesystem::path>(&paths["nodesdata"]), ".nodes file") //
|
||||
("edgesdata", value<boost::filesystem::path>(&paths["edgesdata"]), ".edges file") //
|
||||
("geometry", value<boost::filesystem::path>(&paths["geometries"]), ".geometry file") //
|
||||
("ramindex", value<boost::filesystem::path>(&paths["ramindex"]), ".ramIndex file") //
|
||||
("fileindex", value<boost::filesystem::path>(&paths["fileindex"]),
|
||||
"File index file") //
|
||||
("namesdata", value<boost::filesystem::path>(&paths["namesdata"]),
|
||||
".names file") //
|
||||
("timestamp", value<boost::filesystem::path>(&paths["timestamp"]),
|
||||
".timestamp file") //
|
||||
("ip,i", value<std::string>(&ip_address)->default_value("0.0.0.0"),
|
||||
"IP address") //
|
||||
("port,p", value<int>(&ip_port)->default_value(5000),
|
||||
"TCP/IP port") //
|
||||
("threads,t", value<int>(&requested_num_threads)->default_value(8),
|
||||
"Number of threads to use") //
|
||||
("shared-memory,s",
|
||||
value<bool>(&use_shared_memory)->implicit_value(true)->default_value(false),
|
||||
"Load data from shared memory") //
|
||||
("max-viaroute-size", value<int>(&max_locations_viaroute)->default_value(500),
|
||||
"Max. locations supported in viaroute query") //
|
||||
("max-trip-size", value<int>(&max_locations_trip)->default_value(100),
|
||||
"Max. locations supported in trip query") //
|
||||
("max-table-size", value<int>(&max_locations_distance_table)->default_value(100),
|
||||
"Max. locations supported in distance table query") //
|
||||
("max-matching-size", value<int>(&max_locations_map_matching)->default_value(100),
|
||||
"Max. locations supported in map matching query");
|
||||
|
||||
// hidden options, will be allowed both on command line and in config
|
||||
// file, but will not be shown to the user
|
||||
boost::program_options::options_description hidden_options("Hidden options");
|
||||
hidden_options.add_options()("base,b", value<boost::filesystem::path>(&paths["base"]),
|
||||
"base path to .osrm file");
|
||||
|
||||
// positional option
|
||||
boost::program_options::positional_options_description positional_options;
|
||||
positional_options.add("base", 1);
|
||||
|
||||
// combine above options for parsing
|
||||
boost::program_options::options_description cmdline_options;
|
||||
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description config_file_options;
|
||||
config_file_options.add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description visible_options(
|
||||
boost::filesystem::basename(argv[0]) + " <base.osrm> [<options>]");
|
||||
visible_options.add(generic_options).add(config_options);
|
||||
|
||||
// parse command line options
|
||||
boost::program_options::variables_map option_variables;
|
||||
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
|
||||
.options(cmdline_options)
|
||||
.positional(positional_options)
|
||||
.run(),
|
||||
option_variables);
|
||||
|
||||
if (option_variables.count("version"))
|
||||
{
|
||||
SimpleLogger().Write() << OSRM_VERSION;
|
||||
return INIT_OK_DO_NOT_START_ENGINE;
|
||||
}
|
||||
|
||||
if (option_variables.count("help"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return INIT_OK_DO_NOT_START_ENGINE;
|
||||
}
|
||||
|
||||
boost::program_options::notify(option_variables);
|
||||
|
||||
// parse config file
|
||||
auto path_iterator = paths.find("config");
|
||||
if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) &&
|
||||
!option_variables.count("base"))
|
||||
{
|
||||
SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string();
|
||||
std::string ini_file_contents = read_file_lower_content(path_iterator->second);
|
||||
std::stringstream config_stream(ini_file_contents);
|
||||
boost::program_options::store(parse_config_file(config_stream, config_file_options),
|
||||
option_variables);
|
||||
boost::program_options::notify(option_variables);
|
||||
return INIT_OK_START_ENGINE;
|
||||
}
|
||||
|
||||
if (1 > requested_num_threads)
|
||||
{
|
||||
throw osrm::exception("Number of threads must be a positive number");
|
||||
}
|
||||
if (2 > max_locations_distance_table)
|
||||
{
|
||||
throw osrm::exception("Max location for distance table must be at least two");
|
||||
}
|
||||
if (2 > max_locations_map_matching)
|
||||
{
|
||||
throw osrm::exception("Max location for map matching must be at least two");
|
||||
}
|
||||
|
||||
if (!use_shared_memory && option_variables.count("base"))
|
||||
{
|
||||
return INIT_OK_START_ENGINE;
|
||||
}
|
||||
else if (use_shared_memory && !option_variables.count("base"))
|
||||
{
|
||||
return INIT_OK_START_ENGINE;
|
||||
}
|
||||
else if (use_shared_memory && option_variables.count("base"))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Shared memory settings conflict with path settings.";
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return INIT_OK_DO_NOT_START_ENGINE;
|
||||
}
|
||||
|
||||
#endif // ROUTED_OPTIONS_HPP
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
||||
#define SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
template <typename DataT> class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT>
|
||||
{
|
||||
DataT *p;
|
||||
|
||||
public:
|
||||
explicit ShMemIterator(DataT *x) : p(x) {}
|
||||
ShMemIterator(const ShMemIterator &mit) : p(mit.p) {}
|
||||
ShMemIterator &operator++()
|
||||
{
|
||||
++p;
|
||||
return *this;
|
||||
}
|
||||
ShMemIterator operator++(int)
|
||||
{
|
||||
ShMemIterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
ShMemIterator operator+(std::ptrdiff_t diff)
|
||||
{
|
||||
ShMemIterator tmp(p + diff);
|
||||
return tmp;
|
||||
}
|
||||
bool operator==(const ShMemIterator &rhs) { return p == rhs.p; }
|
||||
bool operator!=(const ShMemIterator &rhs) { return p != rhs.p; }
|
||||
DataT &operator*() { return *p; }
|
||||
};
|
||||
|
||||
template <typename DataT> class SharedMemoryWrapper
|
||||
{
|
||||
private:
|
||||
DataT *m_ptr;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
|
||||
|
||||
SharedMemoryWrapper(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
|
||||
void swap(SharedMemoryWrapper<DataT> &other)
|
||||
{
|
||||
// BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||
std::swap(m_size, other.m_size);
|
||||
std::swap(m_ptr, other.m_ptr);
|
||||
}
|
||||
|
||||
DataT &at(const std::size_t index) { return m_ptr[index]; }
|
||||
|
||||
const DataT &at(const std::size_t index) const { return m_ptr[index]; }
|
||||
|
||||
ShMemIterator<DataT> begin() const { return ShMemIterator<DataT>(m_ptr); }
|
||||
|
||||
ShMemIterator<DataT> end() const { return ShMemIterator<DataT>(m_ptr + m_size); }
|
||||
|
||||
std::size_t size() const { return m_size; }
|
||||
|
||||
bool empty() const { return 0 == size(); }
|
||||
|
||||
DataT &operator[](const unsigned index)
|
||||
{
|
||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||
return m_ptr[index];
|
||||
}
|
||||
|
||||
const DataT &operator[](const unsigned index) const
|
||||
{
|
||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||
return m_ptr[index];
|
||||
}
|
||||
};
|
||||
|
||||
template <> class SharedMemoryWrapper<bool>
|
||||
{
|
||||
private:
|
||||
unsigned *m_ptr;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
|
||||
|
||||
SharedMemoryWrapper(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
|
||||
void swap(SharedMemoryWrapper<bool> &other)
|
||||
{
|
||||
// BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||
std::swap(m_size, other.m_size);
|
||||
std::swap(m_ptr, other.m_ptr);
|
||||
}
|
||||
|
||||
bool at(const std::size_t index) const
|
||||
{
|
||||
const std::size_t bucket = index / 32;
|
||||
const unsigned offset = static_cast<unsigned>(index % 32);
|
||||
return m_ptr[bucket] & (1 << offset);
|
||||
}
|
||||
|
||||
std::size_t size() const { return m_size; }
|
||||
|
||||
bool empty() const { return 0 == size(); }
|
||||
|
||||
bool operator[](const unsigned index)
|
||||
{
|
||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||
const unsigned bucket = index / 32;
|
||||
const unsigned offset = index % 32;
|
||||
return m_ptr[bucket] & (1 << offset);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DataT, bool UseSharedMemory> struct ShM
|
||||
{
|
||||
using vector = typename std::conditional<UseSharedMemory,
|
||||
SharedMemoryWrapper<DataT>,
|
||||
std::vector<DataT>>::type;
|
||||
};
|
||||
|
||||
#endif // SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SIMPLE_LOGGER_HPP
|
||||
#define SIMPLE_LOGGER_HPP
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
|
||||
enum LogLevel
|
||||
{
|
||||
logINFO,
|
||||
logWARNING,
|
||||
logDEBUG
|
||||
};
|
||||
|
||||
class LogPolicy
|
||||
{
|
||||
public:
|
||||
void Unmute();
|
||||
|
||||
void Mute();
|
||||
|
||||
bool IsMute() const;
|
||||
|
||||
static LogPolicy &GetInstance();
|
||||
|
||||
LogPolicy(const LogPolicy &) = delete;
|
||||
|
||||
private:
|
||||
LogPolicy() : m_is_mute(true) {}
|
||||
std::atomic<bool> m_is_mute;
|
||||
};
|
||||
|
||||
class SimpleLogger
|
||||
{
|
||||
public:
|
||||
SimpleLogger();
|
||||
|
||||
virtual ~SimpleLogger();
|
||||
std::mutex &get_mutex();
|
||||
std::ostringstream &Write(LogLevel l = logINFO) noexcept;
|
||||
|
||||
private:
|
||||
std::ostringstream os;
|
||||
LogLevel level;
|
||||
};
|
||||
|
||||
#endif /* SIMPLE_LOGGER_HPP */
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef STATIC_GRAPH_HPP
|
||||
#define STATIC_GRAPH_HPP
|
||||
|
||||
#include "percent.hpp"
|
||||
#include "shared_memory_vector_wrapper.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
{
|
||||
public:
|
||||
using NodeIterator = NodeID;
|
||||
using EdgeIterator = NodeID;
|
||||
using EdgeData = EdgeDataT;
|
||||
using EdgeRange = osrm::range<EdgeIterator>;
|
||||
|
||||
class InputEdge
|
||||
{
|
||||
public:
|
||||
NodeIterator source;
|
||||
NodeIterator target;
|
||||
EdgeDataT data;
|
||||
|
||||
template <typename... Ts>
|
||||
InputEdge(NodeIterator source, NodeIterator target, Ts &&... data)
|
||||
: source(source), target(target), data(std::forward<Ts>(data)...)
|
||||
{
|
||||
}
|
||||
bool operator<(const InputEdge &right) const
|
||||
{
|
||||
if (source != right.source)
|
||||
{
|
||||
return source < right.source;
|
||||
}
|
||||
return target < right.target;
|
||||
}
|
||||
};
|
||||
|
||||
struct NodeArrayEntry
|
||||
{
|
||||
// index of the first edge
|
||||
EdgeIterator first_edge;
|
||||
};
|
||||
|
||||
struct EdgeArrayEntry
|
||||
{
|
||||
NodeID target;
|
||||
EdgeDataT data;
|
||||
};
|
||||
|
||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
||||
{
|
||||
return osrm::irange(BeginEdges(node), EndEdges(node));
|
||||
}
|
||||
|
||||
template<typename ContainerT>
|
||||
StaticGraph(const int nodes, const ContainerT &graph)
|
||||
{
|
||||
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT&>(graph).begin(), const_cast<ContainerT&>(graph).end()));
|
||||
|
||||
number_of_nodes = nodes;
|
||||
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
||||
node_array.resize(number_of_nodes + 1);
|
||||
EdgeIterator edge = 0;
|
||||
EdgeIterator position = 0;
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes + 1))
|
||||
{
|
||||
EdgeIterator last_edge = edge;
|
||||
while (edge < number_of_edges && graph[edge].source == node)
|
||||
{
|
||||
++edge;
|
||||
}
|
||||
node_array[node].first_edge = position; //=edge
|
||||
position += edge - last_edge; // remove
|
||||
}
|
||||
edge_array.resize(position); //(edge)
|
||||
edge = 0;
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||
{
|
||||
EdgeIterator e = node_array[node + 1].first_edge;
|
||||
for (const auto i : osrm::irange(node_array[node].first_edge, e))
|
||||
{
|
||||
edge_array[i].target = graph[edge].target;
|
||||
edge_array[i].data = graph[edge].data;
|
||||
edge++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
|
||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
|
||||
{
|
||||
number_of_nodes = static_cast<decltype(number_of_nodes)>(nodes.size() - 1);
|
||||
number_of_edges = static_cast<decltype(number_of_edges)>(edges.size());
|
||||
|
||||
node_array.swap(nodes);
|
||||
edge_array.swap(edges);
|
||||
}
|
||||
|
||||
unsigned GetNumberOfNodes() const { return number_of_nodes; }
|
||||
|
||||
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
||||
|
||||
unsigned GetOutDegree(const NodeIterator n) const { return EndEdges(n) - BeginEdges(n); }
|
||||
|
||||
inline NodeIterator GetTarget(const EdgeIterator e) const
|
||||
{
|
||||
return NodeIterator(edge_array[e].target);
|
||||
}
|
||||
|
||||
EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
|
||||
|
||||
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
|
||||
|
||||
EdgeIterator BeginEdges(const NodeIterator n) const
|
||||
{
|
||||
return EdgeIterator(node_array.at(n).first_edge);
|
||||
}
|
||||
|
||||
EdgeIterator EndEdges(const NodeIterator n) const
|
||||
{
|
||||
return EdgeIterator(node_array.at(n + 1).first_edge);
|
||||
}
|
||||
|
||||
// searches for a specific edge
|
||||
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
for (const auto i : osrm::irange(BeginEdges(from), EndEdges(from)))
|
||||
{
|
||||
if (to == edge_array[i].target)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return SPECIAL_EDGEID;
|
||||
}
|
||||
|
||||
// searches for a specific edge
|
||||
EdgeIterator FindSmallestEdge(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
EdgeIterator smallest_edge = SPECIAL_EDGEID;
|
||||
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
|
||||
for (auto edge : GetAdjacentEdgeRange(from))
|
||||
{
|
||||
const NodeID target = GetTarget(edge);
|
||||
const EdgeWeight weight = GetEdgeData(edge).distance;
|
||||
if (target == to && weight < smallest_weight)
|
||||
{
|
||||
smallest_edge = edge;
|
||||
smallest_weight = weight;
|
||||
}
|
||||
}
|
||||
return smallest_edge;
|
||||
}
|
||||
|
||||
EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
|
||||
{
|
||||
EdgeIterator tmp = FindEdge(from, to);
|
||||
return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
|
||||
}
|
||||
|
||||
EdgeIterator
|
||||
FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const
|
||||
{
|
||||
EdgeIterator current_iterator = FindEdge(from, to);
|
||||
if (SPECIAL_NODEID == current_iterator)
|
||||
{
|
||||
current_iterator = FindEdge(to, from);
|
||||
if (SPECIAL_NODEID != current_iterator)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return current_iterator;
|
||||
}
|
||||
|
||||
private:
|
||||
NodeIterator number_of_nodes;
|
||||
EdgeIterator number_of_edges;
|
||||
|
||||
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
|
||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
|
||||
};
|
||||
|
||||
#endif // STATIC_GRAPH_HPP
|
||||
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef STATIC_RTREE_HPP
|
||||
#define STATIC_RTREE_HPP
|
||||
|
||||
#include "deallocating_vector.hpp"
|
||||
#include "hilbert_value.hpp"
|
||||
#include "rectangle.hpp"
|
||||
#include "shared_memory_factory.hpp"
|
||||
#include "shared_memory_vector_wrapper.hpp"
|
||||
|
||||
#include "../util/bearing.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/mercator.hpp"
|
||||
#include "../util/osrm_exception.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <variant/variant.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Static RTree for serving nearest neighbour queries
|
||||
template <class EdgeDataT,
|
||||
class CoordinateListT = std::vector<FixedPointCoordinate>,
|
||||
bool UseSharedMemory = false,
|
||||
uint32_t BRANCHING_FACTOR = 64,
|
||||
uint32_t LEAF_NODE_SIZE = 1024>
|
||||
class StaticRTree
|
||||
{
|
||||
public:
|
||||
using Rectangle = RectangleInt2D;
|
||||
using EdgeData = EdgeDataT;
|
||||
using CoordinateList = CoordinateListT;
|
||||
|
||||
static constexpr std::size_t MAX_CHECKED_ELEMENTS = 4 * LEAF_NODE_SIZE;
|
||||
|
||||
struct TreeNode
|
||||
{
|
||||
TreeNode() : child_count(0), child_is_on_disk(false) {}
|
||||
Rectangle minimum_bounding_rectangle;
|
||||
uint32_t child_count : 31;
|
||||
bool child_is_on_disk : 1;
|
||||
uint32_t children[BRANCHING_FACTOR];
|
||||
};
|
||||
|
||||
private:
|
||||
struct WrappedInputElement
|
||||
{
|
||||
explicit WrappedInputElement(const uint64_t _hilbert_value, const uint32_t _array_index)
|
||||
: m_hilbert_value(_hilbert_value), m_array_index(_array_index)
|
||||
{
|
||||
}
|
||||
|
||||
WrappedInputElement() : m_hilbert_value(0), m_array_index(UINT_MAX) {}
|
||||
|
||||
uint64_t m_hilbert_value;
|
||||
uint32_t m_array_index;
|
||||
|
||||
inline bool operator<(const WrappedInputElement &other) const
|
||||
{
|
||||
return m_hilbert_value < other.m_hilbert_value;
|
||||
}
|
||||
};
|
||||
|
||||
struct LeafNode
|
||||
{
|
||||
LeafNode() : object_count(0), objects() {}
|
||||
uint32_t object_count;
|
||||
std::array<EdgeDataT, LEAF_NODE_SIZE> objects;
|
||||
};
|
||||
|
||||
using QueryNodeType = mapbox::util::variant<TreeNode, EdgeDataT>;
|
||||
struct QueryCandidate
|
||||
{
|
||||
inline bool operator<(const QueryCandidate &other) const
|
||||
{
|
||||
// Attn: this is reversed order. std::pq is a max pq!
|
||||
return other.min_dist < min_dist;
|
||||
}
|
||||
|
||||
float min_dist;
|
||||
QueryNodeType node;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
public:
|
||||
StaticRTree() = delete;
|
||||
StaticRTree(const StaticRTree &) = delete;
|
||||
|
||||
template <typename CoordinateT>
|
||||
// Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
|
||||
explicit StaticRTree(const std::vector<EdgeDataT> &input_data_vector,
|
||||
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)
|
||||
{
|
||||
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
|
||||
|
||||
HilbertCode get_hilbert_number;
|
||||
|
||||
// generate auxiliary vector of hilbert-values
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<uint64_t>(0, m_element_count),
|
||||
[&input_data_vector, &input_wrapper_vector, &get_hilbert_number,
|
||||
&coordinate_list](const tbb::blocked_range<uint64_t> &range)
|
||||
{
|
||||
for (uint64_t element_counter = range.begin(), end = range.end();
|
||||
element_counter != end; ++element_counter)
|
||||
{
|
||||
WrappedInputElement ¤t_wrapper = input_wrapper_vector[element_counter];
|
||||
current_wrapper.m_array_index = element_counter;
|
||||
|
||||
EdgeDataT const ¤t_element = input_data_vector[element_counter];
|
||||
|
||||
// Get Hilbert-Value for centroid in mercartor projection
|
||||
FixedPointCoordinate current_centroid = EdgeDataT::Centroid(
|
||||
FixedPointCoordinate(coordinate_list.at(current_element.u).lat,
|
||||
coordinate_list.at(current_element.u).lon),
|
||||
FixedPointCoordinate(coordinate_list.at(current_element.v).lat,
|
||||
coordinate_list.at(current_element.v).lon));
|
||||
current_centroid.lat =
|
||||
COORDINATE_PRECISION *
|
||||
mercator::lat2y(current_centroid.lat / COORDINATE_PRECISION);
|
||||
|
||||
current_wrapper.m_hilbert_value = get_hilbert_number(current_centroid);
|
||||
}
|
||||
});
|
||||
|
||||
// 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());
|
||||
std::vector<TreeNode> tree_nodes_in_level;
|
||||
|
||||
// pack M elements into leaf node and write to leaf file
|
||||
uint64_t processed_objects_count = 0;
|
||||
while (processed_objects_count < m_element_count)
|
||||
{
|
||||
|
||||
LeafNode current_leaf;
|
||||
TreeNode current_node;
|
||||
for (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))
|
||||
{
|
||||
uint32_t index_of_next_object =
|
||||
input_wrapper_vector[processed_objects_count + current_element_index]
|
||||
.m_array_index;
|
||||
current_leaf.objects[current_element_index] =
|
||||
input_data_vector[index_of_next_object];
|
||||
++current_leaf.object_count;
|
||||
}
|
||||
}
|
||||
|
||||
// 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_node.child_is_on_disk = true;
|
||||
current_node.children[0] = tree_nodes_in_level.size();
|
||||
tree_nodes_in_level.emplace_back(current_node);
|
||||
|
||||
// write leaf_node to leaf node file
|
||||
leaf_node_file.write((char *)¤t_leaf, sizeof(current_leaf));
|
||||
processed_objects_count += current_leaf.object_count;
|
||||
}
|
||||
|
||||
// close leaf file
|
||||
leaf_node_file.close();
|
||||
|
||||
uint32_t processing_level = 0;
|
||||
while (1 < tree_nodes_in_level.size())
|
||||
{
|
||||
std::vector<TreeNode> tree_nodes_in_next_level;
|
||||
uint32_t processed_tree_nodes_in_level = 0;
|
||||
while (processed_tree_nodes_in_level < tree_nodes_in_level.size())
|
||||
{
|
||||
TreeNode parent_node;
|
||||
// pack BRANCHING_FACTOR elements into tree_nodes each
|
||||
for (uint32_t current_child_node_index = 0;
|
||||
BRANCHING_FACTOR > current_child_node_index; ++current_child_node_index)
|
||||
{
|
||||
if (processed_tree_nodes_in_level < tree_nodes_in_level.size())
|
||||
{
|
||||
TreeNode ¤t_child_node =
|
||||
tree_nodes_in_level[processed_tree_nodes_in_level];
|
||||
// add tree node to parent entry
|
||||
parent_node.children[current_child_node_index] = m_search_tree.size();
|
||||
m_search_tree.emplace_back(current_child_node);
|
||||
// merge MBRs
|
||||
parent_node.minimum_bounding_rectangle.MergeBoundingBoxes(
|
||||
current_child_node.minimum_bounding_rectangle);
|
||||
// increase counters
|
||||
++parent_node.child_count;
|
||||
++processed_tree_nodes_in_level;
|
||||
}
|
||||
}
|
||||
tree_nodes_in_next_level.emplace_back(parent_node);
|
||||
}
|
||||
tree_nodes_in_level.swap(tree_nodes_in_next_level);
|
||||
++processing_level;
|
||||
}
|
||||
BOOST_ASSERT_MSG(1 == tree_nodes_in_level.size(), "tree broken, more than one root node");
|
||||
// last remaining entry is the root node, store it
|
||||
m_search_tree.emplace_back(tree_nodes_in_level[0]);
|
||||
|
||||
// reverse and renumber tree to have root at index 0
|
||||
std::reverse(m_search_tree.begin(), m_search_tree.end());
|
||||
|
||||
uint32_t search_tree_size = m_search_tree.size();
|
||||
tbb::parallel_for(tbb::blocked_range<uint32_t>(0, search_tree_size),
|
||||
[this, &search_tree_size](const tbb::blocked_range<uint32_t> &range)
|
||||
{
|
||||
for (uint32_t i = range.begin(), end = range.end(); i != end; ++i)
|
||||
{
|
||||
TreeNode ¤t_tree_node = this->m_search_tree[i];
|
||||
for (uint32_t j = 0; j < current_tree_node.child_count; ++j)
|
||||
{
|
||||
const uint32_t old_id = current_tree_node.children[j];
|
||||
const uint32_t new_id = search_tree_size - old_id - 1;
|
||||
current_tree_node.children[j] = new_id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// open tree file
|
||||
boost::filesystem::ofstream tree_node_file(tree_node_filename, std::ios::binary);
|
||||
|
||||
uint32_t size_of_tree = m_search_tree.size();
|
||||
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
||||
tree_node_file.write((char *)&size_of_tree, sizeof(uint32_t));
|
||||
tree_node_file.write((char *)&m_search_tree[0], sizeof(TreeNode) * size_of_tree);
|
||||
// close tree node file.
|
||||
tree_node_file.close();
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
// open tree node file and load into RAM.
|
||||
m_coordinate_list = coordinate_list;
|
||||
|
||||
if (!boost::filesystem::exists(node_file))
|
||||
{
|
||||
throw osrm::exception("ram index file does not exist");
|
||||
}
|
||||
if (0 == boost::filesystem::file_size(node_file))
|
||||
{
|
||||
throw osrm::exception("ram index file is empty");
|
||||
}
|
||||
boost::filesystem::ifstream tree_node_file(node_file, std::ios::binary);
|
||||
|
||||
uint32_t tree_size = 0;
|
||||
tree_node_file.read((char *)&tree_size, sizeof(uint32_t));
|
||||
|
||||
m_search_tree.resize(tree_size);
|
||||
if (tree_size > 0)
|
||||
{
|
||||
tree_node_file.read((char *)&m_search_tree[0], sizeof(TreeNode) * tree_size);
|
||||
}
|
||||
tree_node_file.close();
|
||||
// open leaf node file and store thread specific pointer
|
||||
if (!boost::filesystem::exists(leaf_file))
|
||||
{
|
||||
throw osrm::exception("mem index file does not exist");
|
||||
}
|
||||
if (0 == boost::filesystem::file_size(leaf_file))
|
||||
{
|
||||
throw osrm::exception("mem index file is empty");
|
||||
}
|
||||
|
||||
leaves_stream.open(leaf_file, std::ios::binary);
|
||||
leaves_stream.read((char *)&m_element_count, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
// open leaf node file and store thread specific pointer
|
||||
if (!boost::filesystem::exists(leaf_file))
|
||||
{
|
||||
throw osrm::exception("mem index file does not exist");
|
||||
}
|
||||
if (0 == boost::filesystem::file_size(leaf_file))
|
||||
{
|
||||
throw osrm::exception("mem index file is empty");
|
||||
}
|
||||
|
||||
leaves_stream.open(leaf_file, std::ios::binary);
|
||||
leaves_stream.read((char *)&m_element_count, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
// Override filter and terminator for the desired behaviour.
|
||||
std::vector<EdgeDataT> Nearest(const FixedPointCoordinate &input_coordinate,
|
||||
const std::size_t max_results)
|
||||
{
|
||||
return Nearest(input_coordinate,
|
||||
[](const EdgeDataT &)
|
||||
{
|
||||
return std::make_pair(true, true);
|
||||
},
|
||||
[max_results](const std::size_t num_results, const float)
|
||||
{
|
||||
return num_results >= max_results;
|
||||
});
|
||||
}
|
||||
|
||||
// Override filter and terminator for the desired behaviour.
|
||||
template <typename FilterT, typename TerminationT>
|
||||
std::vector<EdgeDataT> Nearest(const FixedPointCoordinate &input_coordinate,
|
||||
const FilterT filter,
|
||||
const TerminationT terminate)
|
||||
{
|
||||
std::vector<EdgeDataT> results;
|
||||
std::pair<double, double> projected_coordinate = {
|
||||
mercator::lat2y(input_coordinate.lat / COORDINATE_PRECISION),
|
||||
input_coordinate.lon / COORDINATE_PRECISION};
|
||||
|
||||
// initialize queue with root element
|
||||
std::priority_queue<QueryCandidate> traversal_queue;
|
||||
traversal_queue.push(QueryCandidate {0.f, m_search_tree[0]});
|
||||
|
||||
while (!traversal_queue.empty())
|
||||
{
|
||||
const QueryCandidate current_query_node = traversal_queue.top();
|
||||
if (terminate(results.size(), current_query_node.min_dist))
|
||||
{
|
||||
traversal_queue = std::priority_queue<QueryCandidate>{};
|
||||
break;
|
||||
}
|
||||
|
||||
traversal_queue.pop();
|
||||
|
||||
if (current_query_node.node.template is<TreeNode>())
|
||||
{ // current object is a tree node
|
||||
const TreeNode ¤t_tree_node =
|
||||
current_query_node.node.template get<TreeNode>();
|
||||
if (current_tree_node.child_is_on_disk)
|
||||
{
|
||||
ExploreLeafNode(current_tree_node.children[0], input_coordinate,
|
||||
projected_coordinate, traversal_queue);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExploreTreeNode(current_tree_node, input_coordinate, traversal_queue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// inspecting an actual road segment
|
||||
const auto ¤t_segment = current_query_node.node.template get<EdgeDataT>();
|
||||
|
||||
|
||||
auto use_segment = filter(current_segment);
|
||||
if (!use_segment.first && !use_segment.second)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// store phantom node in result vector
|
||||
results.push_back(std::move(current_segment));
|
||||
|
||||
if (!use_segment.first)
|
||||
{
|
||||
results.back().forward_edge_based_node_id = SPECIAL_NODEID;
|
||||
}
|
||||
else if (!use_segment.second)
|
||||
{
|
||||
results.back().reverse_edge_based_node_id = SPECIAL_NODEID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename QueueT>
|
||||
void ExploreLeafNode(const std::uint32_t leaf_id,
|
||||
const FixedPointCoordinate &input_coordinate,
|
||||
const std::pair<double, double> &projected_coordinate,
|
||||
QueueT &traversal_queue)
|
||||
{
|
||||
LeafNode current_leaf_node;
|
||||
LoadLeafFromDisk(leaf_id, current_leaf_node);
|
||||
|
||||
// current object represents a block on disk
|
||||
for (const auto i : osrm::irange(0u, current_leaf_node.object_count))
|
||||
{
|
||||
auto ¤t_edge = current_leaf_node.objects[i];
|
||||
const float current_perpendicular_distance =
|
||||
coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
m_coordinate_list->at(current_edge.u), m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate, projected_coordinate);
|
||||
// distance must be non-negative
|
||||
BOOST_ASSERT(0.f <= current_perpendicular_distance);
|
||||
|
||||
traversal_queue.push(QueryCandidate {current_perpendicular_distance, std::move(current_edge)});
|
||||
}
|
||||
}
|
||||
|
||||
template <class QueueT>
|
||||
void ExploreTreeNode(const TreeNode &parent,
|
||||
const FixedPointCoordinate &input_coordinate,
|
||||
QueueT &traversal_queue)
|
||||
{
|
||||
for (uint32_t i = 0; i < parent.child_count; ++i)
|
||||
{
|
||||
const int32_t child_id = parent.children[i];
|
||||
const auto &child_tree_node = m_search_tree[child_id];
|
||||
const auto &child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||
const float lower_bound_to_element = child_rectangle.GetMinDist(input_coordinate);
|
||||
traversal_queue.push(QueryCandidate {lower_bound_to_element, m_search_tree[child_id]});
|
||||
}
|
||||
}
|
||||
|
||||
inline void LoadLeafFromDisk(const 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 osrm::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,
|
||||
const uint32_t element_count,
|
||||
const std::vector<CoordinateT> &coordinate_list)
|
||||
{
|
||||
for (uint32_t i = 0; i < element_count; ++i)
|
||||
{
|
||||
rectangle.min_lon =
|
||||
std::min(rectangle.min_lon, std::min(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
rectangle.max_lon =
|
||||
std::max(rectangle.max_lon, std::max(coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon));
|
||||
|
||||
rectangle.min_lat =
|
||||
std::min(rectangle.min_lat, std::min(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
rectangle.max_lat =
|
||||
std::max(rectangle.max_lat, std::max(coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat));
|
||||
}
|
||||
BOOST_ASSERT(rectangle.min_lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(rectangle.min_lon != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(rectangle.max_lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(rectangle.max_lon != std::numeric_limits<int>::min());
|
||||
}
|
||||
};
|
||||
|
||||
//[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403
|
||||
//[2] "Nearest Neighbor Queries", N. Roussopulos et al; 1995; DOI: 10.1145/223784.223794
|
||||
//[3] "Distance Browsing in Spatial Databases"; G. Hjaltason, H. Samet; 1999; ACM Trans. DB Sys
|
||||
// Vol.24 No.2, pp.265-318
|
||||
#endif // STATIC_RTREE_HPP
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef STD_HASH_HPP
|
||||
#define STD_HASH_HPP
|
||||
|
||||
#include <functional>
|
||||
|
||||
// this is largely inspired by boost's hash combine as can be found in
|
||||
// "The C++ Standard Library" 2nd Edition. Nicolai M. Josuttis. 2012.
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename T> void hash_combine(std::size_t &seed, const T &val)
|
||||
{
|
||||
seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
|
||||
template <typename T> void hash_val(std::size_t &seed, const T &val) { hash_combine(seed, val); }
|
||||
|
||||
template <typename T, typename... Types>
|
||||
void hash_val(std::size_t &seed, const T &val, const Types &... args)
|
||||
{
|
||||
hash_combine(seed, val);
|
||||
hash_val(seed, args...);
|
||||
}
|
||||
|
||||
template <typename... Types> std::size_t hash_val(const Types &... args)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
hash_val(seed, args...);
|
||||
return seed;
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T1, typename T2> struct hash<std::pair<T1, T2>>
|
||||
{
|
||||
size_t operator()(const std::pair<T1, T2> &pair) const
|
||||
{
|
||||
return hash_val(pair.first, pair.second);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // STD_HASH_HPP
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef STRING_UTIL_HPP
|
||||
#define STRING_UTIL_HPP
|
||||
|
||||
#include <cctype>
|
||||
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// precision: position after decimal point
|
||||
// length: maximum number of digits including comma and decimals
|
||||
// work with negative values to prevent overflowing when taking -value
|
||||
template <int length, int precision> static inline char *printInt(char *buffer, int value)
|
||||
{
|
||||
static_assert(length > 0, "length must be positive");
|
||||
static_assert(precision > 0, "precision must be positive");
|
||||
|
||||
const bool minus = [&value]
|
||||
{
|
||||
if (value >= 0)
|
||||
{
|
||||
value = -value;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
|
||||
buffer += length - 1;
|
||||
for (int i = 0; i < precision; ++i)
|
||||
{
|
||||
*buffer = '0' - (value % 10);
|
||||
value /= 10;
|
||||
--buffer;
|
||||
}
|
||||
*buffer = '.';
|
||||
--buffer;
|
||||
|
||||
for (int i = precision + 1; i < length; ++i)
|
||||
{
|
||||
*buffer = '0' - (value % 10);
|
||||
value /= 10;
|
||||
if (value == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
--buffer;
|
||||
}
|
||||
|
||||
if (minus)
|
||||
{
|
||||
--buffer;
|
||||
*buffer = '-';
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline std::string escape_JSON(const std::string &input)
|
||||
{
|
||||
// escape and skip reallocations if possible
|
||||
std::string output;
|
||||
output.reserve(input.size() + 4); // +4 assumes two backslashes on avg
|
||||
for (const char letter : input)
|
||||
{
|
||||
switch (letter)
|
||||
{
|
||||
case '\\':
|
||||
output += "\\\\";
|
||||
break;
|
||||
case '"':
|
||||
output += "\\\"";
|
||||
break;
|
||||
case '/':
|
||||
output += "\\/";
|
||||
break;
|
||||
case '\b':
|
||||
output += "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
output += "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
output += "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
output += "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
output += "\\t";
|
||||
break;
|
||||
default:
|
||||
output.append(1, letter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
inline std::size_t URIDecode(const std::string &input, std::string &output)
|
||||
{
|
||||
auto src_iter = std::begin(input);
|
||||
const auto src_end = std::end(input);
|
||||
output.resize(input.size() + 1);
|
||||
std::size_t decoded_length = 0;
|
||||
for (decoded_length = 0; src_iter != src_end; ++decoded_length)
|
||||
{
|
||||
if (src_iter[0] == '%' && src_iter[1] && src_iter[2] && isxdigit(src_iter[1]) &&
|
||||
isxdigit(src_iter[2]))
|
||||
{
|
||||
std::string::value_type a = src_iter[1];
|
||||
std::string::value_type b = src_iter[2];
|
||||
a -= src_iter[1] < 58 ? 48 : src_iter[1] < 71 ? 55 : 87;
|
||||
b -= src_iter[2] < 58 ? 48 : src_iter[2] < 71 ? 55 : 87;
|
||||
output[decoded_length] = 16 * a + b;
|
||||
src_iter += 3;
|
||||
continue;
|
||||
}
|
||||
output[decoded_length] = *src_iter++;
|
||||
}
|
||||
output.resize(decoded_length);
|
||||
return decoded_length;
|
||||
}
|
||||
|
||||
inline std::size_t URIDecodeInPlace(std::string &URI) { return URIDecode(URI, URI); }
|
||||
|
||||
#endif // STRING_UTIL_HPP
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TIMING_UTIL_HPP
|
||||
#define TIMING_UTIL_HPP
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
struct GlobalTimer
|
||||
{
|
||||
GlobalTimer() : time(0) {}
|
||||
std::atomic<uint64_t> time;
|
||||
};
|
||||
|
||||
class GlobalTimerFactory
|
||||
{
|
||||
public:
|
||||
static GlobalTimerFactory &get()
|
||||
{
|
||||
static GlobalTimerFactory instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
GlobalTimer &getGlobalTimer(const std::string &name)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(map_mutex);
|
||||
return timer_map[name];
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex map_mutex;
|
||||
std::unordered_map<std::string, GlobalTimer> timer_map;
|
||||
};
|
||||
|
||||
#define GLOBAL_TIMER_AQUIRE(_X) \
|
||||
auto &_X##_global_timer = GlobalTimerFactory::get().getGlobalTimer(#_X)
|
||||
#define GLOBAL_TIMER_RESET(_X) _X##_global_timer.time = 0
|
||||
#define GLOBAL_TIMER_START(_X) TIMER_START(_X)
|
||||
#define GLOBAL_TIMER_STOP(_X) \
|
||||
TIMER_STOP(_X); \
|
||||
_X##_global_timer.time += TIMER_NSEC(_X)
|
||||
#define GLOBAL_TIMER_NSEC(_X) static_cast<double>(_X##_global_timer.time)
|
||||
#define GLOBAL_TIMER_USEC(_X) (_X##_global_timer.time / 1000.0)
|
||||
#define GLOBAL_TIMER_MSEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0)
|
||||
#define GLOBAL_TIMER_SEC(_X) (_X##_global_timer.time / 1000.0 / 1000.0 / 1000.0)
|
||||
|
||||
#define TIMER_START(_X) auto _X##_start = std::chrono::steady_clock::now(), _X##_stop = _X##_start
|
||||
#define TIMER_STOP(_X) _X##_stop = std::chrono::steady_clock::now()
|
||||
#define TIMER_NSEC(_X) \
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(_X##_stop - _X##_start).count()
|
||||
#define TIMER_USEC(_X) \
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(_X##_stop - _X##_start).count()
|
||||
#define TIMER_MSEC(_X) \
|
||||
(0.000001 * \
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(_X##_stop - _X##_start).count())
|
||||
#define TIMER_SEC(_X) \
|
||||
(0.000001 * \
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(_X##_stop - _X##_start).count())
|
||||
#define TIMER_MIN(_X) \
|
||||
std::chrono::duration_cast<std::chrono::minutes>(_X##_stop - _X##_start).count()
|
||||
|
||||
#endif // TIMING_UTIL_HPP
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TRIBOOL_HPP
|
||||
#define TRIBOOL_HPP
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
enum class tribool : char
|
||||
{
|
||||
yes,
|
||||
no,
|
||||
indeterminate
|
||||
};
|
||||
}
|
||||
#endif // TRIBOOL_HPP
|
||||
@@ -0,0 +1,448 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TRIGONOMETRY_TABLE_HPP
|
||||
#define TRIGONOMETRY_TABLE_HPP
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
|
||||
constexpr unsigned short atan_table[4096] = {
|
||||
0x0000, 0x0014, 0x0028, 0x003d, 0x0051, 0x0065, 0x007a, 0x008e, 0x00a3, 0x00b7, 0x00cb, 0x00e0,
|
||||
0x00f4, 0x0108, 0x011d, 0x0131, 0x0146, 0x015a, 0x016e, 0x0183, 0x0197, 0x01ab, 0x01c0, 0x01d4,
|
||||
0x01e9, 0x01fd, 0x0211, 0x0226, 0x023a, 0x024e, 0x0263, 0x0277, 0x028c, 0x02a0, 0x02b4, 0x02c9,
|
||||
0x02dd, 0x02f1, 0x0306, 0x031a, 0x032f, 0x0343, 0x0357, 0x036c, 0x0380, 0x0394, 0x03a9, 0x03bd,
|
||||
0x03d2, 0x03e6, 0x03fa, 0x040f, 0x0423, 0x0437, 0x044c, 0x0460, 0x0475, 0x0489, 0x049d, 0x04b2,
|
||||
0x04c6, 0x04da, 0x04ef, 0x0503, 0x0517, 0x052c, 0x0540, 0x0555, 0x0569, 0x057d, 0x0592, 0x05a6,
|
||||
0x05ba, 0x05cf, 0x05e3, 0x05f8, 0x060c, 0x0620, 0x0635, 0x0649, 0x065d, 0x0672, 0x0686, 0x069b,
|
||||
0x06af, 0x06c3, 0x06d8, 0x06ec, 0x0700, 0x0715, 0x0729, 0x073d, 0x0752, 0x0766, 0x077b, 0x078f,
|
||||
0x07a3, 0x07b8, 0x07cc, 0x07e0, 0x07f5, 0x0809, 0x081d, 0x0832, 0x0846, 0x085b, 0x086f, 0x0883,
|
||||
0x0898, 0x08ac, 0x08c0, 0x08d5, 0x08e9, 0x08fd, 0x0912, 0x0926, 0x093b, 0x094f, 0x0963, 0x0978,
|
||||
0x098c, 0x09a0, 0x09b5, 0x09c9, 0x09dd, 0x09f2, 0x0a06, 0x0a1a, 0x0a2f, 0x0a43, 0x0a58, 0x0a6c,
|
||||
0x0a80, 0x0a95, 0x0aa9, 0x0abd, 0x0ad2, 0x0ae6, 0x0afa, 0x0b0f, 0x0b23, 0x0b37, 0x0b4c, 0x0b60,
|
||||
0x0b75, 0x0b89, 0x0b9d, 0x0bb2, 0x0bc6, 0x0bda, 0x0bef, 0x0c03, 0x0c17, 0x0c2c, 0x0c40, 0x0c54,
|
||||
0x0c69, 0x0c7d, 0x0c91, 0x0ca6, 0x0cba, 0x0cce, 0x0ce3, 0x0cf7, 0x0d0b, 0x0d20, 0x0d34, 0x0d48,
|
||||
0x0d5d, 0x0d71, 0x0d86, 0x0d9a, 0x0dae, 0x0dc3, 0x0dd7, 0x0deb, 0x0e00, 0x0e14, 0x0e28, 0x0e3d,
|
||||
0x0e51, 0x0e65, 0x0e7a, 0x0e8e, 0x0ea2, 0x0eb7, 0x0ecb, 0x0edf, 0x0ef4, 0x0f08, 0x0f1c, 0x0f31,
|
||||
0x0f45, 0x0f59, 0x0f6e, 0x0f82, 0x0f96, 0x0fab, 0x0fbf, 0x0fd3, 0x0fe8, 0x0ffc, 0x1010, 0x1025,
|
||||
0x1039, 0x104d, 0x1062, 0x1076, 0x108a, 0x109e, 0x10b3, 0x10c7, 0x10db, 0x10f0, 0x1104, 0x1118,
|
||||
0x112d, 0x1141, 0x1155, 0x116a, 0x117e, 0x1192, 0x11a7, 0x11bb, 0x11cf, 0x11e4, 0x11f8, 0x120c,
|
||||
0x1221, 0x1235, 0x1249, 0x125d, 0x1272, 0x1286, 0x129a, 0x12af, 0x12c3, 0x12d7, 0x12ec, 0x1300,
|
||||
0x1314, 0x1329, 0x133d, 0x1351, 0x1365, 0x137a, 0x138e, 0x13a2, 0x13b7, 0x13cb, 0x13df, 0x13f4,
|
||||
0x1408, 0x141c, 0x1431, 0x1445, 0x1459, 0x146d, 0x1482, 0x1496, 0x14aa, 0x14bf, 0x14d3, 0x14e7,
|
||||
0x14fb, 0x1510, 0x1524, 0x1538, 0x154d, 0x1561, 0x1575, 0x1589, 0x159e, 0x15b2, 0x15c6, 0x15db,
|
||||
0x15ef, 0x1603, 0x1617, 0x162c, 0x1640, 0x1654, 0x1669, 0x167d, 0x1691, 0x16a5, 0x16ba, 0x16ce,
|
||||
0x16e2, 0x16f7, 0x170b, 0x171f, 0x1733, 0x1748, 0x175c, 0x1770, 0x1784, 0x1799, 0x17ad, 0x17c1,
|
||||
0x17d6, 0x17ea, 0x17fe, 0x1812, 0x1827, 0x183b, 0x184f, 0x1863, 0x1878, 0x188c, 0x18a0, 0x18b4,
|
||||
0x18c9, 0x18dd, 0x18f1, 0x1905, 0x191a, 0x192e, 0x1942, 0x1957, 0x196b, 0x197f, 0x1993, 0x19a8,
|
||||
0x19bc, 0x19d0, 0x19e4, 0x19f9, 0x1a0d, 0x1a21, 0x1a35, 0x1a49, 0x1a5e, 0x1a72, 0x1a86, 0x1a9a,
|
||||
0x1aaf, 0x1ac3, 0x1ad7, 0x1aeb, 0x1b00, 0x1b14, 0x1b28, 0x1b3c, 0x1b51, 0x1b65, 0x1b79, 0x1b8d,
|
||||
0x1ba2, 0x1bb6, 0x1bca, 0x1bde, 0x1bf2, 0x1c07, 0x1c1b, 0x1c2f, 0x1c43, 0x1c58, 0x1c6c, 0x1c80,
|
||||
0x1c94, 0x1ca8, 0x1cbd, 0x1cd1, 0x1ce5, 0x1cf9, 0x1d0e, 0x1d22, 0x1d36, 0x1d4a, 0x1d5e, 0x1d73,
|
||||
0x1d87, 0x1d9b, 0x1daf, 0x1dc3, 0x1dd8, 0x1dec, 0x1e00, 0x1e14, 0x1e28, 0x1e3d, 0x1e51, 0x1e65,
|
||||
0x1e79, 0x1e8d, 0x1ea2, 0x1eb6, 0x1eca, 0x1ede, 0x1ef2, 0x1f07, 0x1f1b, 0x1f2f, 0x1f43, 0x1f57,
|
||||
0x1f6c, 0x1f80, 0x1f94, 0x1fa8, 0x1fbc, 0x1fd1, 0x1fe5, 0x1ff9, 0x200d, 0x2021, 0x2035, 0x204a,
|
||||
0x205e, 0x2072, 0x2086, 0x209a, 0x20ae, 0x20c3, 0x20d7, 0x20eb, 0x20ff, 0x2113, 0x2127, 0x213c,
|
||||
0x2150, 0x2164, 0x2178, 0x218c, 0x21a0, 0x21b5, 0x21c9, 0x21dd, 0x21f1, 0x2205, 0x2219, 0x222e,
|
||||
0x2242, 0x2256, 0x226a, 0x227e, 0x2292, 0x22a6, 0x22bb, 0x22cf, 0x22e3, 0x22f7, 0x230b, 0x231f,
|
||||
0x2333, 0x2348, 0x235c, 0x2370, 0x2384, 0x2398, 0x23ac, 0x23c0, 0x23d5, 0x23e9, 0x23fd, 0x2411,
|
||||
0x2425, 0x2439, 0x244d, 0x2461, 0x2476, 0x248a, 0x249e, 0x24b2, 0x24c6, 0x24da, 0x24ee, 0x2502,
|
||||
0x2517, 0x252b, 0x253f, 0x2553, 0x2567, 0x257b, 0x258f, 0x25a3, 0x25b7, 0x25cb, 0x25e0, 0x25f4,
|
||||
0x2608, 0x261c, 0x2630, 0x2644, 0x2658, 0x266c, 0x2680, 0x2694, 0x26a9, 0x26bd, 0x26d1, 0x26e5,
|
||||
0x26f9, 0x270d, 0x2721, 0x2735, 0x2749, 0x275d, 0x2771, 0x2785, 0x279a, 0x27ae, 0x27c2, 0x27d6,
|
||||
0x27ea, 0x27fe, 0x2812, 0x2826, 0x283a, 0x284e, 0x2862, 0x2876, 0x288a, 0x289e, 0x28b3, 0x28c7,
|
||||
0x28db, 0x28ef, 0x2903, 0x2917, 0x292b, 0x293f, 0x2953, 0x2967, 0x297b, 0x298f, 0x29a3, 0x29b7,
|
||||
0x29cb, 0x29df, 0x29f3, 0x2a07, 0x2a1b, 0x2a2f, 0x2a43, 0x2a58, 0x2a6c, 0x2a80, 0x2a94, 0x2aa8,
|
||||
0x2abc, 0x2ad0, 0x2ae4, 0x2af8, 0x2b0c, 0x2b20, 0x2b34, 0x2b48, 0x2b5c, 0x2b70, 0x2b84, 0x2b98,
|
||||
0x2bac, 0x2bc0, 0x2bd4, 0x2be8, 0x2bfc, 0x2c10, 0x2c24, 0x2c38, 0x2c4c, 0x2c60, 0x2c74, 0x2c88,
|
||||
0x2c9c, 0x2cb0, 0x2cc4, 0x2cd8, 0x2cec, 0x2d00, 0x2d14, 0x2d28, 0x2d3c, 0x2d50, 0x2d64, 0x2d78,
|
||||
0x2d8c, 0x2da0, 0x2db4, 0x2dc8, 0x2ddc, 0x2df0, 0x2e04, 0x2e18, 0x2e2c, 0x2e40, 0x2e54, 0x2e68,
|
||||
0x2e7c, 0x2e90, 0x2ea3, 0x2eb7, 0x2ecb, 0x2edf, 0x2ef3, 0x2f07, 0x2f1b, 0x2f2f, 0x2f43, 0x2f57,
|
||||
0x2f6b, 0x2f7f, 0x2f93, 0x2fa7, 0x2fbb, 0x2fcf, 0x2fe3, 0x2ff7, 0x300b, 0x301e, 0x3032, 0x3046,
|
||||
0x305a, 0x306e, 0x3082, 0x3096, 0x30aa, 0x30be, 0x30d2, 0x30e6, 0x30fa, 0x310e, 0x3122, 0x3135,
|
||||
0x3149, 0x315d, 0x3171, 0x3185, 0x3199, 0x31ad, 0x31c1, 0x31d5, 0x31e9, 0x31fd, 0x3210, 0x3224,
|
||||
0x3238, 0x324c, 0x3260, 0x3274, 0x3288, 0x329c, 0x32b0, 0x32c3, 0x32d7, 0x32eb, 0x32ff, 0x3313,
|
||||
0x3327, 0x333b, 0x334f, 0x3363, 0x3376, 0x338a, 0x339e, 0x33b2, 0x33c6, 0x33da, 0x33ee, 0x3401,
|
||||
0x3415, 0x3429, 0x343d, 0x3451, 0x3465, 0x3479, 0x348c, 0x34a0, 0x34b4, 0x34c8, 0x34dc, 0x34f0,
|
||||
0x3504, 0x3517, 0x352b, 0x353f, 0x3553, 0x3567, 0x357b, 0x358e, 0x35a2, 0x35b6, 0x35ca, 0x35de,
|
||||
0x35f2, 0x3605, 0x3619, 0x362d, 0x3641, 0x3655, 0x3668, 0x367c, 0x3690, 0x36a4, 0x36b8, 0x36cb,
|
||||
0x36df, 0x36f3, 0x3707, 0x371b, 0x372f, 0x3742, 0x3756, 0x376a, 0x377e, 0x3791, 0x37a5, 0x37b9,
|
||||
0x37cd, 0x37e1, 0x37f4, 0x3808, 0x381c, 0x3830, 0x3844, 0x3857, 0x386b, 0x387f, 0x3893, 0x38a6,
|
||||
0x38ba, 0x38ce, 0x38e2, 0x38f5, 0x3909, 0x391d, 0x3931, 0x3944, 0x3958, 0x396c, 0x3980, 0x3993,
|
||||
0x39a7, 0x39bb, 0x39cf, 0x39e2, 0x39f6, 0x3a0a, 0x3a1e, 0x3a31, 0x3a45, 0x3a59, 0x3a6d, 0x3a80,
|
||||
0x3a94, 0x3aa8, 0x3abb, 0x3acf, 0x3ae3, 0x3af7, 0x3b0a, 0x3b1e, 0x3b32, 0x3b45, 0x3b59, 0x3b6d,
|
||||
0x3b81, 0x3b94, 0x3ba8, 0x3bbc, 0x3bcf, 0x3be3, 0x3bf7, 0x3c0b, 0x3c1e, 0x3c32, 0x3c46, 0x3c59,
|
||||
0x3c6d, 0x3c81, 0x3c94, 0x3ca8, 0x3cbc, 0x3ccf, 0x3ce3, 0x3cf7, 0x3d0a, 0x3d1e, 0x3d32, 0x3d45,
|
||||
0x3d59, 0x3d6d, 0x3d80, 0x3d94, 0x3da8, 0x3dbb, 0x3dcf, 0x3de3, 0x3df6, 0x3e0a, 0x3e1e, 0x3e31,
|
||||
0x3e45, 0x3e59, 0x3e6c, 0x3e80, 0x3e93, 0x3ea7, 0x3ebb, 0x3ece, 0x3ee2, 0x3ef6, 0x3f09, 0x3f1d,
|
||||
0x3f30, 0x3f44, 0x3f58, 0x3f6b, 0x3f7f, 0x3f93, 0x3fa6, 0x3fba, 0x3fcd, 0x3fe1, 0x3ff5, 0x4008,
|
||||
0x401c, 0x402f, 0x4043, 0x4057, 0x406a, 0x407e, 0x4091, 0x40a5, 0x40b8, 0x40cc, 0x40e0, 0x40f3,
|
||||
0x4107, 0x411a, 0x412e, 0x4142, 0x4155, 0x4169, 0x417c, 0x4190, 0x41a3, 0x41b7, 0x41ca, 0x41de,
|
||||
0x41f2, 0x4205, 0x4219, 0x422c, 0x4240, 0x4253, 0x4267, 0x427a, 0x428e, 0x42a1, 0x42b5, 0x42c9,
|
||||
0x42dc, 0x42f0, 0x4303, 0x4317, 0x432a, 0x433e, 0x4351, 0x4365, 0x4378, 0x438c, 0x439f, 0x43b3,
|
||||
0x43c6, 0x43da, 0x43ed, 0x4401, 0x4414, 0x4428, 0x443b, 0x444f, 0x4462, 0x4476, 0x4489, 0x449d,
|
||||
0x44b0, 0x44c4, 0x44d7, 0x44eb, 0x44fe, 0x4512, 0x4525, 0x4539, 0x454c, 0x4560, 0x4573, 0x4586,
|
||||
0x459a, 0x45ad, 0x45c1, 0x45d4, 0x45e8, 0x45fb, 0x460f, 0x4622, 0x4636, 0x4649, 0x465c, 0x4670,
|
||||
0x4683, 0x4697, 0x46aa, 0x46be, 0x46d1, 0x46e5, 0x46f8, 0x470b, 0x471f, 0x4732, 0x4746, 0x4759,
|
||||
0x476c, 0x4780, 0x4793, 0x47a7, 0x47ba, 0x47cd, 0x47e1, 0x47f4, 0x4808, 0x481b, 0x482e, 0x4842,
|
||||
0x4855, 0x4869, 0x487c, 0x488f, 0x48a3, 0x48b6, 0x48ca, 0x48dd, 0x48f0, 0x4904, 0x4917, 0x492a,
|
||||
0x493e, 0x4951, 0x4965, 0x4978, 0x498b, 0x499f, 0x49b2, 0x49c5, 0x49d9, 0x49ec, 0x49ff, 0x4a13,
|
||||
0x4a26, 0x4a39, 0x4a4d, 0x4a60, 0x4a73, 0x4a87, 0x4a9a, 0x4aad, 0x4ac1, 0x4ad4, 0x4ae7, 0x4afb,
|
||||
0x4b0e, 0x4b21, 0x4b35, 0x4b48, 0x4b5b, 0x4b6f, 0x4b82, 0x4b95, 0x4ba8, 0x4bbc, 0x4bcf, 0x4be2,
|
||||
0x4bf6, 0x4c09, 0x4c1c, 0x4c2f, 0x4c43, 0x4c56, 0x4c69, 0x4c7d, 0x4c90, 0x4ca3, 0x4cb6, 0x4cca,
|
||||
0x4cdd, 0x4cf0, 0x4d03, 0x4d17, 0x4d2a, 0x4d3d, 0x4d50, 0x4d64, 0x4d77, 0x4d8a, 0x4d9d, 0x4db1,
|
||||
0x4dc4, 0x4dd7, 0x4dea, 0x4dfe, 0x4e11, 0x4e24, 0x4e37, 0x4e4b, 0x4e5e, 0x4e71, 0x4e84, 0x4e97,
|
||||
0x4eab, 0x4ebe, 0x4ed1, 0x4ee4, 0x4ef7, 0x4f0b, 0x4f1e, 0x4f31, 0x4f44, 0x4f57, 0x4f6b, 0x4f7e,
|
||||
0x4f91, 0x4fa4, 0x4fb7, 0x4fcb, 0x4fde, 0x4ff1, 0x5004, 0x5017, 0x502a, 0x503e, 0x5051, 0x5064,
|
||||
0x5077, 0x508a, 0x509d, 0x50b1, 0x50c4, 0x50d7, 0x50ea, 0x50fd, 0x5110, 0x5123, 0x5137, 0x514a,
|
||||
0x515d, 0x5170, 0x5183, 0x5196, 0x51a9, 0x51bc, 0x51d0, 0x51e3, 0x51f6, 0x5209, 0x521c, 0x522f,
|
||||
0x5242, 0x5255, 0x5268, 0x527c, 0x528f, 0x52a2, 0x52b5, 0x52c8, 0x52db, 0x52ee, 0x5301, 0x5314,
|
||||
0x5327, 0x533a, 0x534e, 0x5361, 0x5374, 0x5387, 0x539a, 0x53ad, 0x53c0, 0x53d3, 0x53e6, 0x53f9,
|
||||
0x540c, 0x541f, 0x5432, 0x5445, 0x5458, 0x546b, 0x547e, 0x5491, 0x54a5, 0x54b8, 0x54cb, 0x54de,
|
||||
0x54f1, 0x5504, 0x5517, 0x552a, 0x553d, 0x5550, 0x5563, 0x5576, 0x5589, 0x559c, 0x55af, 0x55c2,
|
||||
0x55d5, 0x55e8, 0x55fb, 0x560e, 0x5621, 0x5634, 0x5647, 0x565a, 0x566d, 0x5680, 0x5693, 0x56a6,
|
||||
0x56b9, 0x56cb, 0x56de, 0x56f1, 0x5704, 0x5717, 0x572a, 0x573d, 0x5750, 0x5763, 0x5776, 0x5789,
|
||||
0x579c, 0x57af, 0x57c2, 0x57d5, 0x57e8, 0x57fb, 0x580e, 0x5820, 0x5833, 0x5846, 0x5859, 0x586c,
|
||||
0x587f, 0x5892, 0x58a5, 0x58b8, 0x58cb, 0x58de, 0x58f0, 0x5903, 0x5916, 0x5929, 0x593c, 0x594f,
|
||||
0x5962, 0x5975, 0x5988, 0x599a, 0x59ad, 0x59c0, 0x59d3, 0x59e6, 0x59f9, 0x5a0c, 0x5a1f, 0x5a31,
|
||||
0x5a44, 0x5a57, 0x5a6a, 0x5a7d, 0x5a90, 0x5aa2, 0x5ab5, 0x5ac8, 0x5adb, 0x5aee, 0x5b01, 0x5b13,
|
||||
0x5b26, 0x5b39, 0x5b4c, 0x5b5f, 0x5b72, 0x5b84, 0x5b97, 0x5baa, 0x5bbd, 0x5bd0, 0x5be2, 0x5bf5,
|
||||
0x5c08, 0x5c1b, 0x5c2e, 0x5c40, 0x5c53, 0x5c66, 0x5c79, 0x5c8c, 0x5c9e, 0x5cb1, 0x5cc4, 0x5cd7,
|
||||
0x5ce9, 0x5cfc, 0x5d0f, 0x5d22, 0x5d34, 0x5d47, 0x5d5a, 0x5d6d, 0x5d7f, 0x5d92, 0x5da5, 0x5db8,
|
||||
0x5dca, 0x5ddd, 0x5df0, 0x5e03, 0x5e15, 0x5e28, 0x5e3b, 0x5e4d, 0x5e60, 0x5e73, 0x5e86, 0x5e98,
|
||||
0x5eab, 0x5ebe, 0x5ed0, 0x5ee3, 0x5ef6, 0x5f09, 0x5f1b, 0x5f2e, 0x5f41, 0x5f53, 0x5f66, 0x5f79,
|
||||
0x5f8b, 0x5f9e, 0x5fb1, 0x5fc3, 0x5fd6, 0x5fe9, 0x5ffb, 0x600e, 0x6021, 0x6033, 0x6046, 0x6059,
|
||||
0x606b, 0x607e, 0x6091, 0x60a3, 0x60b6, 0x60c8, 0x60db, 0x60ee, 0x6100, 0x6113, 0x6126, 0x6138,
|
||||
0x614b, 0x615d, 0x6170, 0x6183, 0x6195, 0x61a8, 0x61ba, 0x61cd, 0x61e0, 0x61f2, 0x6205, 0x6217,
|
||||
0x622a, 0x623d, 0x624f, 0x6262, 0x6274, 0x6287, 0x6299, 0x62ac, 0x62bf, 0x62d1, 0x62e4, 0x62f6,
|
||||
0x6309, 0x631b, 0x632e, 0x6340, 0x6353, 0x6366, 0x6378, 0x638b, 0x639d, 0x63b0, 0x63c2, 0x63d5,
|
||||
0x63e7, 0x63fa, 0x640c, 0x641f, 0x6431, 0x6444, 0x6456, 0x6469, 0x647b, 0x648e, 0x64a0, 0x64b3,
|
||||
0x64c5, 0x64d8, 0x64ea, 0x64fd, 0x650f, 0x6522, 0x6534, 0x6547, 0x6559, 0x656c, 0x657e, 0x6591,
|
||||
0x65a3, 0x65b5, 0x65c8, 0x65da, 0x65ed, 0x65ff, 0x6612, 0x6624, 0x6637, 0x6649, 0x665b, 0x666e,
|
||||
0x6680, 0x6693, 0x66a5, 0x66b8, 0x66ca, 0x66dc, 0x66ef, 0x6701, 0x6714, 0x6726, 0x6738, 0x674b,
|
||||
0x675d, 0x6770, 0x6782, 0x6794, 0x67a7, 0x67b9, 0x67cc, 0x67de, 0x67f0, 0x6803, 0x6815, 0x6827,
|
||||
0x683a, 0x684c, 0x685e, 0x6871, 0x6883, 0x6896, 0x68a8, 0x68ba, 0x68cd, 0x68df, 0x68f1, 0x6904,
|
||||
0x6916, 0x6928, 0x693b, 0x694d, 0x695f, 0x6972, 0x6984, 0x6996, 0x69a8, 0x69bb, 0x69cd, 0x69df,
|
||||
0x69f2, 0x6a04, 0x6a16, 0x6a29, 0x6a3b, 0x6a4d, 0x6a5f, 0x6a72, 0x6a84, 0x6a96, 0x6aa9, 0x6abb,
|
||||
0x6acd, 0x6adf, 0x6af2, 0x6b04, 0x6b16, 0x6b28, 0x6b3b, 0x6b4d, 0x6b5f, 0x6b71, 0x6b84, 0x6b96,
|
||||
0x6ba8, 0x6bba, 0x6bcd, 0x6bdf, 0x6bf1, 0x6c03, 0x6c15, 0x6c28, 0x6c3a, 0x6c4c, 0x6c5e, 0x6c70,
|
||||
0x6c83, 0x6c95, 0x6ca7, 0x6cb9, 0x6ccb, 0x6cde, 0x6cf0, 0x6d02, 0x6d14, 0x6d26, 0x6d39, 0x6d4b,
|
||||
0x6d5d, 0x6d6f, 0x6d81, 0x6d93, 0x6da6, 0x6db8, 0x6dca, 0x6ddc, 0x6dee, 0x6e00, 0x6e12, 0x6e25,
|
||||
0x6e37, 0x6e49, 0x6e5b, 0x6e6d, 0x6e7f, 0x6e91, 0x6ea3, 0x6eb6, 0x6ec8, 0x6eda, 0x6eec, 0x6efe,
|
||||
0x6f10, 0x6f22, 0x6f34, 0x6f46, 0x6f58, 0x6f6b, 0x6f7d, 0x6f8f, 0x6fa1, 0x6fb3, 0x6fc5, 0x6fd7,
|
||||
0x6fe9, 0x6ffb, 0x700d, 0x701f, 0x7031, 0x7043, 0x7055, 0x7068, 0x707a, 0x708c, 0x709e, 0x70b0,
|
||||
0x70c2, 0x70d4, 0x70e6, 0x70f8, 0x710a, 0x711c, 0x712e, 0x7140, 0x7152, 0x7164, 0x7176, 0x7188,
|
||||
0x719a, 0x71ac, 0x71be, 0x71d0, 0x71e2, 0x71f4, 0x7206, 0x7218, 0x722a, 0x723c, 0x724e, 0x7260,
|
||||
0x7272, 0x7284, 0x7296, 0x72a8, 0x72ba, 0x72cc, 0x72dd, 0x72ef, 0x7301, 0x7313, 0x7325, 0x7337,
|
||||
0x7349, 0x735b, 0x736d, 0x737f, 0x7391, 0x73a3, 0x73b5, 0x73c7, 0x73d8, 0x73ea, 0x73fc, 0x740e,
|
||||
0x7420, 0x7432, 0x7444, 0x7456, 0x7468, 0x747a, 0x748b, 0x749d, 0x74af, 0x74c1, 0x74d3, 0x74e5,
|
||||
0x74f7, 0x7509, 0x751a, 0x752c, 0x753e, 0x7550, 0x7562, 0x7574, 0x7585, 0x7597, 0x75a9, 0x75bb,
|
||||
0x75cd, 0x75df, 0x75f0, 0x7602, 0x7614, 0x7626, 0x7638, 0x764a, 0x765b, 0x766d, 0x767f, 0x7691,
|
||||
0x76a3, 0x76b4, 0x76c6, 0x76d8, 0x76ea, 0x76fb, 0x770d, 0x771f, 0x7731, 0x7743, 0x7754, 0x7766,
|
||||
0x7778, 0x778a, 0x779b, 0x77ad, 0x77bf, 0x77d1, 0x77e2, 0x77f4, 0x7806, 0x7818, 0x7829, 0x783b,
|
||||
0x784d, 0x785e, 0x7870, 0x7882, 0x7894, 0x78a5, 0x78b7, 0x78c9, 0x78da, 0x78ec, 0x78fe, 0x7910,
|
||||
0x7921, 0x7933, 0x7945, 0x7956, 0x7968, 0x797a, 0x798b, 0x799d, 0x79af, 0x79c0, 0x79d2, 0x79e4,
|
||||
0x79f5, 0x7a07, 0x7a19, 0x7a2a, 0x7a3c, 0x7a4e, 0x7a5f, 0x7a71, 0x7a82, 0x7a94, 0x7aa6, 0x7ab7,
|
||||
0x7ac9, 0x7adb, 0x7aec, 0x7afe, 0x7b0f, 0x7b21, 0x7b33, 0x7b44, 0x7b56, 0x7b67, 0x7b79, 0x7b8b,
|
||||
0x7b9c, 0x7bae, 0x7bbf, 0x7bd1, 0x7be2, 0x7bf4, 0x7c06, 0x7c17, 0x7c29, 0x7c3a, 0x7c4c, 0x7c5d,
|
||||
0x7c6f, 0x7c81, 0x7c92, 0x7ca4, 0x7cb5, 0x7cc7, 0x7cd8, 0x7cea, 0x7cfb, 0x7d0d, 0x7d1e, 0x7d30,
|
||||
0x7d41, 0x7d53, 0x7d64, 0x7d76, 0x7d87, 0x7d99, 0x7daa, 0x7dbc, 0x7dcd, 0x7ddf, 0x7df0, 0x7e02,
|
||||
0x7e13, 0x7e25, 0x7e36, 0x7e48, 0x7e59, 0x7e6b, 0x7e7c, 0x7e8e, 0x7e9f, 0x7eb0, 0x7ec2, 0x7ed3,
|
||||
0x7ee5, 0x7ef6, 0x7f08, 0x7f19, 0x7f2b, 0x7f3c, 0x7f4d, 0x7f5f, 0x7f70, 0x7f82, 0x7f93, 0x7fa4,
|
||||
0x7fb6, 0x7fc7, 0x7fd9, 0x7fea, 0x7ffb, 0x800d, 0x801e, 0x8030, 0x8041, 0x8052, 0x8064, 0x8075,
|
||||
0x8086, 0x8098, 0x80a9, 0x80bb, 0x80cc, 0x80dd, 0x80ef, 0x8100, 0x8111, 0x8123, 0x8134, 0x8145,
|
||||
0x8157, 0x8168, 0x8179, 0x818b, 0x819c, 0x81ad, 0x81bf, 0x81d0, 0x81e1, 0x81f3, 0x8204, 0x8215,
|
||||
0x8226, 0x8238, 0x8249, 0x825a, 0x826c, 0x827d, 0x828e, 0x829f, 0x82b1, 0x82c2, 0x82d3, 0x82e5,
|
||||
0x82f6, 0x8307, 0x8318, 0x832a, 0x833b, 0x834c, 0x835d, 0x836f, 0x8380, 0x8391, 0x83a2, 0x83b3,
|
||||
0x83c5, 0x83d6, 0x83e7, 0x83f8, 0x840a, 0x841b, 0x842c, 0x843d, 0x844e, 0x8460, 0x8471, 0x8482,
|
||||
0x8493, 0x84a4, 0x84b6, 0x84c7, 0x84d8, 0x84e9, 0x84fa, 0x850b, 0x851d, 0x852e, 0x853f, 0x8550,
|
||||
0x8561, 0x8572, 0x8584, 0x8595, 0x85a6, 0x85b7, 0x85c8, 0x85d9, 0x85ea, 0x85fb, 0x860d, 0x861e,
|
||||
0x862f, 0x8640, 0x8651, 0x8662, 0x8673, 0x8684, 0x8695, 0x86a7, 0x86b8, 0x86c9, 0x86da, 0x86eb,
|
||||
0x86fc, 0x870d, 0x871e, 0x872f, 0x8740, 0x8751, 0x8762, 0x8773, 0x8784, 0x8796, 0x87a7, 0x87b8,
|
||||
0x87c9, 0x87da, 0x87eb, 0x87fc, 0x880d, 0x881e, 0x882f, 0x8840, 0x8851, 0x8862, 0x8873, 0x8884,
|
||||
0x8895, 0x88a6, 0x88b7, 0x88c8, 0x88d9, 0x88ea, 0x88fb, 0x890c, 0x891d, 0x892e, 0x893f, 0x8950,
|
||||
0x8961, 0x8972, 0x8983, 0x8994, 0x89a5, 0x89b6, 0x89c6, 0x89d7, 0x89e8, 0x89f9, 0x8a0a, 0x8a1b,
|
||||
0x8a2c, 0x8a3d, 0x8a4e, 0x8a5f, 0x8a70, 0x8a81, 0x8a92, 0x8aa3, 0x8ab3, 0x8ac4, 0x8ad5, 0x8ae6,
|
||||
0x8af7, 0x8b08, 0x8b19, 0x8b2a, 0x8b3b, 0x8b4b, 0x8b5c, 0x8b6d, 0x8b7e, 0x8b8f, 0x8ba0, 0x8bb1,
|
||||
0x8bc1, 0x8bd2, 0x8be3, 0x8bf4, 0x8c05, 0x8c16, 0x8c27, 0x8c37, 0x8c48, 0x8c59, 0x8c6a, 0x8c7b,
|
||||
0x8c8c, 0x8c9c, 0x8cad, 0x8cbe, 0x8ccf, 0x8ce0, 0x8cf0, 0x8d01, 0x8d12, 0x8d23, 0x8d34, 0x8d44,
|
||||
0x8d55, 0x8d66, 0x8d77, 0x8d87, 0x8d98, 0x8da9, 0x8dba, 0x8dca, 0x8ddb, 0x8dec, 0x8dfd, 0x8e0d,
|
||||
0x8e1e, 0x8e2f, 0x8e40, 0x8e50, 0x8e61, 0x8e72, 0x8e83, 0x8e93, 0x8ea4, 0x8eb5, 0x8ec5, 0x8ed6,
|
||||
0x8ee7, 0x8ef8, 0x8f08, 0x8f19, 0x8f2a, 0x8f3a, 0x8f4b, 0x8f5c, 0x8f6c, 0x8f7d, 0x8f8e, 0x8f9e,
|
||||
0x8faf, 0x8fc0, 0x8fd0, 0x8fe1, 0x8ff2, 0x9002, 0x9013, 0x9024, 0x9034, 0x9045, 0x9056, 0x9066,
|
||||
0x9077, 0x9088, 0x9098, 0x90a9, 0x90b9, 0x90ca, 0x90db, 0x90eb, 0x90fc, 0x910c, 0x911d, 0x912e,
|
||||
0x913e, 0x914f, 0x915f, 0x9170, 0x9181, 0x9191, 0x91a2, 0x91b2, 0x91c3, 0x91d3, 0x91e4, 0x91f5,
|
||||
0x9205, 0x9216, 0x9226, 0x9237, 0x9247, 0x9258, 0x9268, 0x9279, 0x9289, 0x929a, 0x92aa, 0x92bb,
|
||||
0x92cc, 0x92dc, 0x92ed, 0x92fd, 0x930e, 0x931e, 0x932f, 0x933f, 0x9350, 0x9360, 0x9370, 0x9381,
|
||||
0x9391, 0x93a2, 0x93b2, 0x93c3, 0x93d3, 0x93e4, 0x93f4, 0x9405, 0x9415, 0x9426, 0x9436, 0x9447,
|
||||
0x9457, 0x9467, 0x9478, 0x9488, 0x9499, 0x94a9, 0x94ba, 0x94ca, 0x94da, 0x94eb, 0x94fb, 0x950c,
|
||||
0x951c, 0x952c, 0x953d, 0x954d, 0x955e, 0x956e, 0x957e, 0x958f, 0x959f, 0x95af, 0x95c0, 0x95d0,
|
||||
0x95e1, 0x95f1, 0x9601, 0x9612, 0x9622, 0x9632, 0x9643, 0x9653, 0x9663, 0x9674, 0x9684, 0x9694,
|
||||
0x96a5, 0x96b5, 0x96c5, 0x96d6, 0x96e6, 0x96f6, 0x9707, 0x9717, 0x9727, 0x9738, 0x9748, 0x9758,
|
||||
0x9768, 0x9779, 0x9789, 0x9799, 0x97aa, 0x97ba, 0x97ca, 0x97da, 0x97eb, 0x97fb, 0x980b, 0x981b,
|
||||
0x982c, 0x983c, 0x984c, 0x985c, 0x986d, 0x987d, 0x988d, 0x989d, 0x98ad, 0x98be, 0x98ce, 0x98de,
|
||||
0x98ee, 0x98ff, 0x990f, 0x991f, 0x992f, 0x993f, 0x9950, 0x9960, 0x9970, 0x9980, 0x9990, 0x99a0,
|
||||
0x99b1, 0x99c1, 0x99d1, 0x99e1, 0x99f1, 0x9a01, 0x9a12, 0x9a22, 0x9a32, 0x9a42, 0x9a52, 0x9a62,
|
||||
0x9a72, 0x9a83, 0x9a93, 0x9aa3, 0x9ab3, 0x9ac3, 0x9ad3, 0x9ae3, 0x9af3, 0x9b04, 0x9b14, 0x9b24,
|
||||
0x9b34, 0x9b44, 0x9b54, 0x9b64, 0x9b74, 0x9b84, 0x9b94, 0x9ba4, 0x9bb5, 0x9bc5, 0x9bd5, 0x9be5,
|
||||
0x9bf5, 0x9c05, 0x9c15, 0x9c25, 0x9c35, 0x9c45, 0x9c55, 0x9c65, 0x9c75, 0x9c85, 0x9c95, 0x9ca5,
|
||||
0x9cb5, 0x9cc5, 0x9cd5, 0x9ce5, 0x9cf5, 0x9d05, 0x9d15, 0x9d25, 0x9d35, 0x9d45, 0x9d55, 0x9d65,
|
||||
0x9d75, 0x9d85, 0x9d95, 0x9da5, 0x9db5, 0x9dc5, 0x9dd5, 0x9de5, 0x9df5, 0x9e05, 0x9e15, 0x9e25,
|
||||
0x9e35, 0x9e45, 0x9e55, 0x9e65, 0x9e74, 0x9e84, 0x9e94, 0x9ea4, 0x9eb4, 0x9ec4, 0x9ed4, 0x9ee4,
|
||||
0x9ef4, 0x9f04, 0x9f14, 0x9f23, 0x9f33, 0x9f43, 0x9f53, 0x9f63, 0x9f73, 0x9f83, 0x9f93, 0x9fa3,
|
||||
0x9fb2, 0x9fc2, 0x9fd2, 0x9fe2, 0x9ff2, 0xa002, 0xa012, 0xa021, 0xa031, 0xa041, 0xa051, 0xa061,
|
||||
0xa071, 0xa080, 0xa090, 0xa0a0, 0xa0b0, 0xa0c0, 0xa0cf, 0xa0df, 0xa0ef, 0xa0ff, 0xa10f, 0xa11e,
|
||||
0xa12e, 0xa13e, 0xa14e, 0xa15e, 0xa16d, 0xa17d, 0xa18d, 0xa19d, 0xa1ac, 0xa1bc, 0xa1cc, 0xa1dc,
|
||||
0xa1eb, 0xa1fb, 0xa20b, 0xa21b, 0xa22a, 0xa23a, 0xa24a, 0xa25a, 0xa269, 0xa279, 0xa289, 0xa298,
|
||||
0xa2a8, 0xa2b8, 0xa2c8, 0xa2d7, 0xa2e7, 0xa2f7, 0xa306, 0xa316, 0xa326, 0xa335, 0xa345, 0xa355,
|
||||
0xa364, 0xa374, 0xa384, 0xa393, 0xa3a3, 0xa3b3, 0xa3c2, 0xa3d2, 0xa3e2, 0xa3f1, 0xa401, 0xa411,
|
||||
0xa420, 0xa430, 0xa440, 0xa44f, 0xa45f, 0xa46e, 0xa47e, 0xa48e, 0xa49d, 0xa4ad, 0xa4bc, 0xa4cc,
|
||||
0xa4dc, 0xa4eb, 0xa4fb, 0xa50a, 0xa51a, 0xa52a, 0xa539, 0xa549, 0xa558, 0xa568, 0xa577, 0xa587,
|
||||
0xa597, 0xa5a6, 0xa5b6, 0xa5c5, 0xa5d5, 0xa5e4, 0xa5f4, 0xa603, 0xa613, 0xa622, 0xa632, 0xa641,
|
||||
0xa651, 0xa660, 0xa670, 0xa67f, 0xa68f, 0xa69e, 0xa6ae, 0xa6bd, 0xa6cd, 0xa6dc, 0xa6ec, 0xa6fb,
|
||||
0xa70b, 0xa71a, 0xa72a, 0xa739, 0xa749, 0xa758, 0xa768, 0xa777, 0xa787, 0xa796, 0xa7a5, 0xa7b5,
|
||||
0xa7c4, 0xa7d4, 0xa7e3, 0xa7f3, 0xa802, 0xa812, 0xa821, 0xa830, 0xa840, 0xa84f, 0xa85f, 0xa86e,
|
||||
0xa87d, 0xa88d, 0xa89c, 0xa8ac, 0xa8bb, 0xa8ca, 0xa8da, 0xa8e9, 0xa8f8, 0xa908, 0xa917, 0xa927,
|
||||
0xa936, 0xa945, 0xa955, 0xa964, 0xa973, 0xa983, 0xa992, 0xa9a1, 0xa9b1, 0xa9c0, 0xa9cf, 0xa9df,
|
||||
0xa9ee, 0xa9fd, 0xaa0d, 0xaa1c, 0xaa2b, 0xaa3b, 0xaa4a, 0xaa59, 0xaa69, 0xaa78, 0xaa87, 0xaa96,
|
||||
0xaaa6, 0xaab5, 0xaac4, 0xaad4, 0xaae3, 0xaaf2, 0xab01, 0xab11, 0xab20, 0xab2f, 0xab3e, 0xab4e,
|
||||
0xab5d, 0xab6c, 0xab7b, 0xab8b, 0xab9a, 0xaba9, 0xabb8, 0xabc7, 0xabd7, 0xabe6, 0xabf5, 0xac04,
|
||||
0xac14, 0xac23, 0xac32, 0xac41, 0xac50, 0xac60, 0xac6f, 0xac7e, 0xac8d, 0xac9c, 0xacab, 0xacbb,
|
||||
0xacca, 0xacd9, 0xace8, 0xacf7, 0xad06, 0xad16, 0xad25, 0xad34, 0xad43, 0xad52, 0xad61, 0xad70,
|
||||
0xad80, 0xad8f, 0xad9e, 0xadad, 0xadbc, 0xadcb, 0xadda, 0xade9, 0xadf8, 0xae08, 0xae17, 0xae26,
|
||||
0xae35, 0xae44, 0xae53, 0xae62, 0xae71, 0xae80, 0xae8f, 0xae9e, 0xaead, 0xaebd, 0xaecc, 0xaedb,
|
||||
0xaeea, 0xaef9, 0xaf08, 0xaf17, 0xaf26, 0xaf35, 0xaf44, 0xaf53, 0xaf62, 0xaf71, 0xaf80, 0xaf8f,
|
||||
0xaf9e, 0xafad, 0xafbc, 0xafcb, 0xafda, 0xafe9, 0xaff8, 0xb007, 0xb016, 0xb025, 0xb034, 0xb043,
|
||||
0xb052, 0xb061, 0xb070, 0xb07f, 0xb08e, 0xb09d, 0xb0ac, 0xb0bb, 0xb0ca, 0xb0d9, 0xb0e8, 0xb0f6,
|
||||
0xb105, 0xb114, 0xb123, 0xb132, 0xb141, 0xb150, 0xb15f, 0xb16e, 0xb17d, 0xb18c, 0xb19b, 0xb1aa,
|
||||
0xb1b8, 0xb1c7, 0xb1d6, 0xb1e5, 0xb1f4, 0xb203, 0xb212, 0xb221, 0xb22f, 0xb23e, 0xb24d, 0xb25c,
|
||||
0xb26b, 0xb27a, 0xb289, 0xb297, 0xb2a6, 0xb2b5, 0xb2c4, 0xb2d3, 0xb2e2, 0xb2f1, 0xb2ff, 0xb30e,
|
||||
0xb31d, 0xb32c, 0xb33b, 0xb349, 0xb358, 0xb367, 0xb376, 0xb385, 0xb393, 0xb3a2, 0xb3b1, 0xb3c0,
|
||||
0xb3cf, 0xb3dd, 0xb3ec, 0xb3fb, 0xb40a, 0xb418, 0xb427, 0xb436, 0xb445, 0xb453, 0xb462, 0xb471,
|
||||
0xb480, 0xb48e, 0xb49d, 0xb4ac, 0xb4bb, 0xb4c9, 0xb4d8, 0xb4e7, 0xb4f6, 0xb504, 0xb513, 0xb522,
|
||||
0xb530, 0xb53f, 0xb54e, 0xb55c, 0xb56b, 0xb57a, 0xb588, 0xb597, 0xb5a6, 0xb5b5, 0xb5c3, 0xb5d2,
|
||||
0xb5e1, 0xb5ef, 0xb5fe, 0xb60d, 0xb61b, 0xb62a, 0xb638, 0xb647, 0xb656, 0xb664, 0xb673, 0xb682,
|
||||
0xb690, 0xb69f, 0xb6ae, 0xb6bc, 0xb6cb, 0xb6d9, 0xb6e8, 0xb6f7, 0xb705, 0xb714, 0xb722, 0xb731,
|
||||
0xb740, 0xb74e, 0xb75d, 0xb76b, 0xb77a, 0xb788, 0xb797, 0xb7a6, 0xb7b4, 0xb7c3, 0xb7d1, 0xb7e0,
|
||||
0xb7ee, 0xb7fd, 0xb80b, 0xb81a, 0xb829, 0xb837, 0xb846, 0xb854, 0xb863, 0xb871, 0xb880, 0xb88e,
|
||||
0xb89d, 0xb8ab, 0xb8ba, 0xb8c8, 0xb8d7, 0xb8e5, 0xb8f4, 0xb902, 0xb911, 0xb91f, 0xb92e, 0xb93c,
|
||||
0xb94b, 0xb959, 0xb968, 0xb976, 0xb984, 0xb993, 0xb9a1, 0xb9b0, 0xb9be, 0xb9cd, 0xb9db, 0xb9ea,
|
||||
0xb9f8, 0xba06, 0xba15, 0xba23, 0xba32, 0xba40, 0xba4f, 0xba5d, 0xba6b, 0xba7a, 0xba88, 0xba97,
|
||||
0xbaa5, 0xbab3, 0xbac2, 0xbad0, 0xbade, 0xbaed, 0xbafb, 0xbb0a, 0xbb18, 0xbb26, 0xbb35, 0xbb43,
|
||||
0xbb51, 0xbb60, 0xbb6e, 0xbb7c, 0xbb8b, 0xbb99, 0xbba8, 0xbbb6, 0xbbc4, 0xbbd3, 0xbbe1, 0xbbef,
|
||||
0xbbfd, 0xbc0c, 0xbc1a, 0xbc28, 0xbc37, 0xbc45, 0xbc53, 0xbc62, 0xbc70, 0xbc7e, 0xbc8c, 0xbc9b,
|
||||
0xbca9, 0xbcb7, 0xbcc6, 0xbcd4, 0xbce2, 0xbcf0, 0xbcff, 0xbd0d, 0xbd1b, 0xbd29, 0xbd38, 0xbd46,
|
||||
0xbd54, 0xbd62, 0xbd71, 0xbd7f, 0xbd8d, 0xbd9b, 0xbdaa, 0xbdb8, 0xbdc6, 0xbdd4, 0xbde2, 0xbdf1,
|
||||
0xbdff, 0xbe0d, 0xbe1b, 0xbe29, 0xbe38, 0xbe46, 0xbe54, 0xbe62, 0xbe70, 0xbe7f, 0xbe8d, 0xbe9b,
|
||||
0xbea9, 0xbeb7, 0xbec5, 0xbed4, 0xbee2, 0xbef0, 0xbefe, 0xbf0c, 0xbf1a, 0xbf28, 0xbf37, 0xbf45,
|
||||
0xbf53, 0xbf61, 0xbf6f, 0xbf7d, 0xbf8b, 0xbf99, 0xbfa7, 0xbfb6, 0xbfc4, 0xbfd2, 0xbfe0, 0xbfee,
|
||||
0xbffc, 0xc00a, 0xc018, 0xc026, 0xc034, 0xc042, 0xc051, 0xc05f, 0xc06d, 0xc07b, 0xc089, 0xc097,
|
||||
0xc0a5, 0xc0b3, 0xc0c1, 0xc0cf, 0xc0dd, 0xc0eb, 0xc0f9, 0xc107, 0xc115, 0xc123, 0xc131, 0xc13f,
|
||||
0xc14d, 0xc15b, 0xc169, 0xc177, 0xc185, 0xc193, 0xc1a1, 0xc1af, 0xc1bd, 0xc1cb, 0xc1d9, 0xc1e7,
|
||||
0xc1f5, 0xc203, 0xc211, 0xc21f, 0xc22d, 0xc23b, 0xc249, 0xc257, 0xc265, 0xc273, 0xc281, 0xc28f,
|
||||
0xc29d, 0xc2ab, 0xc2b8, 0xc2c6, 0xc2d4, 0xc2e2, 0xc2f0, 0xc2fe, 0xc30c, 0xc31a, 0xc328, 0xc336,
|
||||
0xc344, 0xc352, 0xc35f, 0xc36d, 0xc37b, 0xc389, 0xc397, 0xc3a5, 0xc3b3, 0xc3c1, 0xc3ce, 0xc3dc,
|
||||
0xc3ea, 0xc3f8, 0xc406, 0xc414, 0xc422, 0xc42f, 0xc43d, 0xc44b, 0xc459, 0xc467, 0xc475, 0xc482,
|
||||
0xc490, 0xc49e, 0xc4ac, 0xc4ba, 0xc4c7, 0xc4d5, 0xc4e3, 0xc4f1, 0xc4ff, 0xc50d, 0xc51a, 0xc528,
|
||||
0xc536, 0xc544, 0xc551, 0xc55f, 0xc56d, 0xc57b, 0xc589, 0xc596, 0xc5a4, 0xc5b2, 0xc5c0, 0xc5cd,
|
||||
0xc5db, 0xc5e9, 0xc5f7, 0xc604, 0xc612, 0xc620, 0xc62d, 0xc63b, 0xc649, 0xc657, 0xc664, 0xc672,
|
||||
0xc680, 0xc68d, 0xc69b, 0xc6a9, 0xc6b7, 0xc6c4, 0xc6d2, 0xc6e0, 0xc6ed, 0xc6fb, 0xc709, 0xc716,
|
||||
0xc724, 0xc732, 0xc73f, 0xc74d, 0xc75b, 0xc768, 0xc776, 0xc784, 0xc791, 0xc79f, 0xc7ad, 0xc7ba,
|
||||
0xc7c8, 0xc7d6, 0xc7e3, 0xc7f1, 0xc7fe, 0xc80c, 0xc81a, 0xc827, 0xc835, 0xc842, 0xc850, 0xc85e,
|
||||
0xc86b, 0xc879, 0xc886, 0xc894, 0xc8a2, 0xc8af, 0xc8bd, 0xc8ca, 0xc8d8, 0xc8e5, 0xc8f3, 0xc901,
|
||||
0xc90e, 0xc91c, 0xc929, 0xc937, 0xc944, 0xc952, 0xc95f, 0xc96d, 0xc97b, 0xc988, 0xc996, 0xc9a3,
|
||||
0xc9b1, 0xc9be, 0xc9cc, 0xc9d9, 0xc9e7, 0xc9f4, 0xca02, 0xca0f, 0xca1d, 0xca2a, 0xca38, 0xca45,
|
||||
0xca53, 0xca60, 0xca6e, 0xca7b, 0xca89, 0xca96, 0xcaa4, 0xcab1, 0xcabe, 0xcacc, 0xcad9, 0xcae7,
|
||||
0xcaf4, 0xcb02, 0xcb0f, 0xcb1d, 0xcb2a, 0xcb37, 0xcb45, 0xcb52, 0xcb60, 0xcb6d, 0xcb7b, 0xcb88,
|
||||
0xcb95, 0xcba3, 0xcbb0, 0xcbbe, 0xcbcb, 0xcbd8, 0xcbe6, 0xcbf3, 0xcc01, 0xcc0e, 0xcc1b, 0xcc29,
|
||||
0xcc36, 0xcc43, 0xcc51, 0xcc5e, 0xcc6c, 0xcc79, 0xcc86, 0xcc94, 0xcca1, 0xccae, 0xccbc, 0xccc9,
|
||||
0xccd6, 0xcce4, 0xccf1, 0xccfe, 0xcd0c, 0xcd19, 0xcd26, 0xcd34, 0xcd41, 0xcd4e, 0xcd5b, 0xcd69,
|
||||
0xcd76, 0xcd83, 0xcd91, 0xcd9e, 0xcdab, 0xcdb9, 0xcdc6, 0xcdd3, 0xcde0, 0xcdee, 0xcdfb, 0xce08,
|
||||
0xce15, 0xce23, 0xce30, 0xce3d, 0xce4a, 0xce58, 0xce65, 0xce72, 0xce7f, 0xce8d, 0xce9a, 0xcea7,
|
||||
0xceb4, 0xcec2, 0xcecf, 0xcedc, 0xcee9, 0xcef6, 0xcf04, 0xcf11, 0xcf1e, 0xcf2b, 0xcf38, 0xcf46,
|
||||
0xcf53, 0xcf60, 0xcf6d, 0xcf7a, 0xcf87, 0xcf95, 0xcfa2, 0xcfaf, 0xcfbc, 0xcfc9, 0xcfd6, 0xcfe4,
|
||||
0xcff1, 0xcffe, 0xd00b, 0xd018, 0xd025, 0xd032, 0xd040, 0xd04d, 0xd05a, 0xd067, 0xd074, 0xd081,
|
||||
0xd08e, 0xd09b, 0xd0a9, 0xd0b6, 0xd0c3, 0xd0d0, 0xd0dd, 0xd0ea, 0xd0f7, 0xd104, 0xd111, 0xd11e,
|
||||
0xd12b, 0xd139, 0xd146, 0xd153, 0xd160, 0xd16d, 0xd17a, 0xd187, 0xd194, 0xd1a1, 0xd1ae, 0xd1bb,
|
||||
0xd1c8, 0xd1d5, 0xd1e2, 0xd1ef, 0xd1fc, 0xd209, 0xd216, 0xd223, 0xd230, 0xd23d, 0xd24a, 0xd257,
|
||||
0xd264, 0xd271, 0xd27e, 0xd28b, 0xd298, 0xd2a5, 0xd2b2, 0xd2bf, 0xd2cc, 0xd2d9, 0xd2e6, 0xd2f3,
|
||||
0xd300, 0xd30d, 0xd31a, 0xd327, 0xd334, 0xd341, 0xd34e, 0xd35b, 0xd368, 0xd375, 0xd382, 0xd38f,
|
||||
0xd39c, 0xd3a8, 0xd3b5, 0xd3c2, 0xd3cf, 0xd3dc, 0xd3e9, 0xd3f6, 0xd403, 0xd410, 0xd41d, 0xd42a,
|
||||
0xd436, 0xd443, 0xd450, 0xd45d, 0xd46a, 0xd477, 0xd484, 0xd491, 0xd49e, 0xd4aa, 0xd4b7, 0xd4c4,
|
||||
0xd4d1, 0xd4de, 0xd4eb, 0xd4f8, 0xd504, 0xd511, 0xd51e, 0xd52b, 0xd538, 0xd545, 0xd551, 0xd55e,
|
||||
0xd56b, 0xd578, 0xd585, 0xd591, 0xd59e, 0xd5ab, 0xd5b8, 0xd5c5, 0xd5d1, 0xd5de, 0xd5eb, 0xd5f8,
|
||||
0xd605, 0xd611, 0xd61e, 0xd62b, 0xd638, 0xd645, 0xd651, 0xd65e, 0xd66b, 0xd678, 0xd684, 0xd691,
|
||||
0xd69e, 0xd6ab, 0xd6b7, 0xd6c4, 0xd6d1, 0xd6de, 0xd6ea, 0xd6f7, 0xd704, 0xd710, 0xd71d, 0xd72a,
|
||||
0xd737, 0xd743, 0xd750, 0xd75d, 0xd769, 0xd776, 0xd783, 0xd78f, 0xd79c, 0xd7a9, 0xd7b6, 0xd7c2,
|
||||
0xd7cf, 0xd7dc, 0xd7e8, 0xd7f5, 0xd802, 0xd80e, 0xd81b, 0xd828, 0xd834, 0xd841, 0xd84e, 0xd85a,
|
||||
0xd867, 0xd873, 0xd880, 0xd88d, 0xd899, 0xd8a6, 0xd8b3, 0xd8bf, 0xd8cc, 0xd8d8, 0xd8e5, 0xd8f2,
|
||||
0xd8fe, 0xd90b, 0xd917, 0xd924, 0xd931, 0xd93d, 0xd94a, 0xd956, 0xd963, 0xd970, 0xd97c, 0xd989,
|
||||
0xd995, 0xd9a2, 0xd9ae, 0xd9bb, 0xd9c8, 0xd9d4, 0xd9e1, 0xd9ed, 0xd9fa, 0xda06, 0xda13, 0xda1f,
|
||||
0xda2c, 0xda38, 0xda45, 0xda51, 0xda5e, 0xda6a, 0xda77, 0xda84, 0xda90, 0xda9d, 0xdaa9, 0xdab6,
|
||||
0xdac2, 0xdacf, 0xdadb, 0xdae7, 0xdaf4, 0xdb00, 0xdb0d, 0xdb19, 0xdb26, 0xdb32, 0xdb3f, 0xdb4b,
|
||||
0xdb58, 0xdb64, 0xdb71, 0xdb7d, 0xdb8a, 0xdb96, 0xdba2, 0xdbaf, 0xdbbb, 0xdbc8, 0xdbd4, 0xdbe1,
|
||||
0xdbed, 0xdbf9, 0xdc06, 0xdc12, 0xdc1f, 0xdc2b, 0xdc38, 0xdc44, 0xdc50, 0xdc5d, 0xdc69, 0xdc76,
|
||||
0xdc82, 0xdc8e, 0xdc9b, 0xdca7, 0xdcb3, 0xdcc0, 0xdccc, 0xdcd9, 0xdce5, 0xdcf1, 0xdcfe, 0xdd0a,
|
||||
0xdd16, 0xdd23, 0xdd2f, 0xdd3b, 0xdd48, 0xdd54, 0xdd60, 0xdd6d, 0xdd79, 0xdd85, 0xdd92, 0xdd9e,
|
||||
0xddaa, 0xddb7, 0xddc3, 0xddcf, 0xdddc, 0xdde8, 0xddf4, 0xde01, 0xde0d, 0xde19, 0xde25, 0xde32,
|
||||
0xde3e, 0xde4a, 0xde57, 0xde63, 0xde6f, 0xde7b, 0xde88, 0xde94, 0xdea0, 0xdeac, 0xdeb9, 0xdec5,
|
||||
0xded1, 0xdedd, 0xdeea, 0xdef6, 0xdf02, 0xdf0e, 0xdf1b, 0xdf27, 0xdf33, 0xdf3f, 0xdf4c, 0xdf58,
|
||||
0xdf64, 0xdf70, 0xdf7c, 0xdf89, 0xdf95, 0xdfa1, 0xdfad, 0xdfb9, 0xdfc6, 0xdfd2, 0xdfde, 0xdfea,
|
||||
0xdff6, 0xe003, 0xe00f, 0xe01b, 0xe027, 0xe033, 0xe03f, 0xe04c, 0xe058, 0xe064, 0xe070, 0xe07c,
|
||||
0xe088, 0xe094, 0xe0a1, 0xe0ad, 0xe0b9, 0xe0c5, 0xe0d1, 0xe0dd, 0xe0e9, 0xe0f5, 0xe102, 0xe10e,
|
||||
0xe11a, 0xe126, 0xe132, 0xe13e, 0xe14a, 0xe156, 0xe162, 0xe16e, 0xe17b, 0xe187, 0xe193, 0xe19f,
|
||||
0xe1ab, 0xe1b7, 0xe1c3, 0xe1cf, 0xe1db, 0xe1e7, 0xe1f3, 0xe1ff, 0xe20b, 0xe217, 0xe223, 0xe22f,
|
||||
0xe23c, 0xe248, 0xe254, 0xe260, 0xe26c, 0xe278, 0xe284, 0xe290, 0xe29c, 0xe2a8, 0xe2b4, 0xe2c0,
|
||||
0xe2cc, 0xe2d8, 0xe2e4, 0xe2f0, 0xe2fc, 0xe308, 0xe314, 0xe320, 0xe32c, 0xe338, 0xe344, 0xe350,
|
||||
0xe35c, 0xe368, 0xe374, 0xe380, 0xe38b, 0xe397, 0xe3a3, 0xe3af, 0xe3bb, 0xe3c7, 0xe3d3, 0xe3df,
|
||||
0xe3eb, 0xe3f7, 0xe403, 0xe40f, 0xe41b, 0xe427, 0xe433, 0xe43f, 0xe44a, 0xe456, 0xe462, 0xe46e,
|
||||
0xe47a, 0xe486, 0xe492, 0xe49e, 0xe4aa, 0xe4b6, 0xe4c1, 0xe4cd, 0xe4d9, 0xe4e5, 0xe4f1, 0xe4fd,
|
||||
0xe509, 0xe515, 0xe520, 0xe52c, 0xe538, 0xe544, 0xe550, 0xe55c, 0xe567, 0xe573, 0xe57f, 0xe58b,
|
||||
0xe597, 0xe5a3, 0xe5af, 0xe5ba, 0xe5c6, 0xe5d2, 0xe5de, 0xe5ea, 0xe5f5, 0xe601, 0xe60d, 0xe619,
|
||||
0xe625, 0xe630, 0xe63c, 0xe648, 0xe654, 0xe660, 0xe66b, 0xe677, 0xe683, 0xe68f, 0xe69a, 0xe6a6,
|
||||
0xe6b2, 0xe6be, 0xe6ca, 0xe6d5, 0xe6e1, 0xe6ed, 0xe6f9, 0xe704, 0xe710, 0xe71c, 0xe727, 0xe733,
|
||||
0xe73f, 0xe74b, 0xe756, 0xe762, 0xe76e, 0xe77a, 0xe785, 0xe791, 0xe79d, 0xe7a8, 0xe7b4, 0xe7c0,
|
||||
0xe7cb, 0xe7d7, 0xe7e3, 0xe7ef, 0xe7fa, 0xe806, 0xe812, 0xe81d, 0xe829, 0xe835, 0xe840, 0xe84c,
|
||||
0xe858, 0xe863, 0xe86f, 0xe87b, 0xe886, 0xe892, 0xe89e, 0xe8a9, 0xe8b5, 0xe8c0, 0xe8cc, 0xe8d8,
|
||||
0xe8e3, 0xe8ef, 0xe8fb, 0xe906, 0xe912, 0xe91d, 0xe929, 0xe935, 0xe940, 0xe94c, 0xe958, 0xe963,
|
||||
0xe96f, 0xe97a, 0xe986, 0xe991, 0xe99d, 0xe9a9, 0xe9b4, 0xe9c0, 0xe9cb, 0xe9d7, 0xe9e3, 0xe9ee,
|
||||
0xe9fa, 0xea05, 0xea11, 0xea1c, 0xea28, 0xea33, 0xea3f, 0xea4a, 0xea56, 0xea62, 0xea6d, 0xea79,
|
||||
0xea84, 0xea90, 0xea9b, 0xeaa7, 0xeab2, 0xeabe, 0xeac9, 0xead5, 0xeae0, 0xeaec, 0xeaf7, 0xeb03,
|
||||
0xeb0e, 0xeb1a, 0xeb25, 0xeb31, 0xeb3c, 0xeb48, 0xeb53, 0xeb5f, 0xeb6a, 0xeb76, 0xeb81, 0xeb8d,
|
||||
0xeb98, 0xeba3, 0xebaf, 0xebba, 0xebc6, 0xebd1, 0xebdd, 0xebe8, 0xebf4, 0xebff, 0xec0a, 0xec16,
|
||||
0xec21, 0xec2d, 0xec38, 0xec44, 0xec4f, 0xec5a, 0xec66, 0xec71, 0xec7d, 0xec88, 0xec93, 0xec9f,
|
||||
0xecaa, 0xecb6, 0xecc1, 0xeccc, 0xecd8, 0xece3, 0xecef, 0xecfa, 0xed05, 0xed11, 0xed1c, 0xed27,
|
||||
0xed33, 0xed3e, 0xed4a, 0xed55, 0xed60, 0xed6c, 0xed77, 0xed82, 0xed8e, 0xed99, 0xeda4, 0xedb0,
|
||||
0xedbb, 0xedc6, 0xedd2, 0xeddd, 0xede8, 0xedf4, 0xedff, 0xee0a, 0xee15, 0xee21, 0xee2c, 0xee37,
|
||||
0xee43, 0xee4e, 0xee59, 0xee65, 0xee70, 0xee7b, 0xee86, 0xee92, 0xee9d, 0xeea8, 0xeeb3, 0xeebf,
|
||||
0xeeca, 0xeed5, 0xeee1, 0xeeec, 0xeef7, 0xef02, 0xef0e, 0xef19, 0xef24, 0xef2f, 0xef3a, 0xef46,
|
||||
0xef51, 0xef5c, 0xef67, 0xef73, 0xef7e, 0xef89, 0xef94, 0xef9f, 0xefab, 0xefb6, 0xefc1, 0xefcc,
|
||||
0xefd7, 0xefe3, 0xefee, 0xeff9, 0xf004, 0xf00f, 0xf01b, 0xf026, 0xf031, 0xf03c, 0xf047, 0xf052,
|
||||
0xf05e, 0xf069, 0xf074, 0xf07f, 0xf08a, 0xf095, 0xf0a1, 0xf0ac, 0xf0b7, 0xf0c2, 0xf0cd, 0xf0d8,
|
||||
0xf0e3, 0xf0ef, 0xf0fa, 0xf105, 0xf110, 0xf11b, 0xf126, 0xf131, 0xf13c, 0xf147, 0xf153, 0xf15e,
|
||||
0xf169, 0xf174, 0xf17f, 0xf18a, 0xf195, 0xf1a0, 0xf1ab, 0xf1b6, 0xf1c2, 0xf1cd, 0xf1d8, 0xf1e3,
|
||||
0xf1ee, 0xf1f9, 0xf204, 0xf20f, 0xf21a, 0xf225, 0xf230, 0xf23b, 0xf246, 0xf251, 0xf25c, 0xf267,
|
||||
0xf272, 0xf27d, 0xf288, 0xf293, 0xf29f, 0xf2aa, 0xf2b5, 0xf2c0, 0xf2cb, 0xf2d6, 0xf2e1, 0xf2ec,
|
||||
0xf2f7, 0xf302, 0xf30d, 0xf318, 0xf323, 0xf32e, 0xf339, 0xf344, 0xf34f, 0xf35a, 0xf364, 0xf36f,
|
||||
0xf37a, 0xf385, 0xf390, 0xf39b, 0xf3a6, 0xf3b1, 0xf3bc, 0xf3c7, 0xf3d2, 0xf3dd, 0xf3e8, 0xf3f3,
|
||||
0xf3fe, 0xf409, 0xf414, 0xf41f, 0xf42a, 0xf435, 0xf43f, 0xf44a, 0xf455, 0xf460, 0xf46b, 0xf476,
|
||||
0xf481, 0xf48c, 0xf497, 0xf4a2, 0xf4ad, 0xf4b7, 0xf4c2, 0xf4cd, 0xf4d8, 0xf4e3, 0xf4ee, 0xf4f9,
|
||||
0xf504, 0xf50f, 0xf519, 0xf524, 0xf52f, 0xf53a, 0xf545, 0xf550, 0xf55b, 0xf565, 0xf570, 0xf57b,
|
||||
0xf586, 0xf591, 0xf59c, 0xf5a6, 0xf5b1, 0xf5bc, 0xf5c7, 0xf5d2, 0xf5dd, 0xf5e7, 0xf5f2, 0xf5fd,
|
||||
0xf608, 0xf613, 0xf61d, 0xf628, 0xf633, 0xf63e, 0xf649, 0xf653, 0xf65e, 0xf669, 0xf674, 0xf67f,
|
||||
0xf689, 0xf694, 0xf69f, 0xf6aa, 0xf6b4, 0xf6bf, 0xf6ca, 0xf6d5, 0xf6e0, 0xf6ea, 0xf6f5, 0xf700,
|
||||
0xf70b, 0xf715, 0xf720, 0xf72b, 0xf736, 0xf740, 0xf74b, 0xf756, 0xf760, 0xf76b, 0xf776, 0xf781,
|
||||
0xf78b, 0xf796, 0xf7a1, 0xf7ab, 0xf7b6, 0xf7c1, 0xf7cc, 0xf7d6, 0xf7e1, 0xf7ec, 0xf7f6, 0xf801,
|
||||
0xf80c, 0xf816, 0xf821, 0xf82c, 0xf836, 0xf841, 0xf84c, 0xf856, 0xf861, 0xf86c, 0xf876, 0xf881,
|
||||
0xf88c, 0xf896, 0xf8a1, 0xf8ac, 0xf8b6, 0xf8c1, 0xf8cc, 0xf8d6, 0xf8e1, 0xf8ec, 0xf8f6, 0xf901,
|
||||
0xf90b, 0xf916, 0xf921, 0xf92b, 0xf936, 0xf941, 0xf94b, 0xf956, 0xf960, 0xf96b, 0xf976, 0xf980,
|
||||
0xf98b, 0xf995, 0xf9a0, 0xf9aa, 0xf9b5, 0xf9c0, 0xf9ca, 0xf9d5, 0xf9df, 0xf9ea, 0xf9f4, 0xf9ff,
|
||||
0xfa0a, 0xfa14, 0xfa1f, 0xfa29, 0xfa34, 0xfa3e, 0xfa49, 0xfa53, 0xfa5e, 0xfa69, 0xfa73, 0xfa7e,
|
||||
0xfa88, 0xfa93, 0xfa9d, 0xfaa8, 0xfab2, 0xfabd, 0xfac7, 0xfad2, 0xfadc, 0xfae7, 0xfaf1, 0xfafc,
|
||||
0xfb06, 0xfb11, 0xfb1b, 0xfb26, 0xfb30, 0xfb3b, 0xfb45, 0xfb50, 0xfb5a, 0xfb65, 0xfb6f, 0xfb7a,
|
||||
0xfb84, 0xfb8f, 0xfb99, 0xfba4, 0xfbae, 0xfbb8, 0xfbc3, 0xfbcd, 0xfbd8, 0xfbe2, 0xfbed, 0xfbf7,
|
||||
0xfc02, 0xfc0c, 0xfc16, 0xfc21, 0xfc2b, 0xfc36, 0xfc40, 0xfc4b, 0xfc55, 0xfc5f, 0xfc6a, 0xfc74,
|
||||
0xfc7f, 0xfc89, 0xfc93, 0xfc9e, 0xfca8, 0xfcb3, 0xfcbd, 0xfcc7, 0xfcd2, 0xfcdc, 0xfce7, 0xfcf1,
|
||||
0xfcfb, 0xfd06, 0xfd10, 0xfd1a, 0xfd25, 0xfd2f, 0xfd3a, 0xfd44, 0xfd4e, 0xfd59, 0xfd63, 0xfd6d,
|
||||
0xfd78, 0xfd82, 0xfd8c, 0xfd97, 0xfda1, 0xfdab, 0xfdb6, 0xfdc0, 0xfdca, 0xfdd5, 0xfddf, 0xfde9,
|
||||
0xfdf4, 0xfdfe, 0xfe08, 0xfe13, 0xfe1d, 0xfe27, 0xfe32, 0xfe3c, 0xfe46, 0xfe50, 0xfe5b, 0xfe65,
|
||||
0xfe6f, 0xfe7a, 0xfe84, 0xfe8e, 0xfe98, 0xfea3, 0xfead, 0xfeb7, 0xfec1, 0xfecc, 0xfed6, 0xfee0,
|
||||
0xfeeb, 0xfef5, 0xfeff, 0xff09, 0xff14, 0xff1e, 0xff28, 0xff32, 0xff3c, 0xff47, 0xff51, 0xff5b,
|
||||
0xff65, 0xff70, 0xff7a, 0xff84, 0xff8e, 0xff98, 0xffa3, 0xffad, 0xffb7, 0xffc1, 0xffcc, 0xffd6,
|
||||
0xffe0, 0xffea, 0xfff4, 0xffff};
|
||||
|
||||
// max value is pi/4
|
||||
constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF;
|
||||
|
||||
inline double atan2_lookup(double y, double x)
|
||||
{
|
||||
if (std::abs(x) < std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
if (y >= 0.)
|
||||
{
|
||||
return M_PI / 2.;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -M_PI / 2.;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned octant = 0;
|
||||
|
||||
if (x < 0.)
|
||||
{
|
||||
octant = 1;
|
||||
x = -x;
|
||||
}
|
||||
if (y < 0.)
|
||||
{
|
||||
octant |= 2;
|
||||
y = -y;
|
||||
}
|
||||
|
||||
double t = y / x;
|
||||
if (t > 1.0)
|
||||
{
|
||||
octant |= 4;
|
||||
t = 1.0 / t;
|
||||
}
|
||||
|
||||
double angle = atan_table[(unsigned)(t * 4095)] / SCALING_FACTOR;
|
||||
|
||||
switch (octant)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
angle = M_PI - angle;
|
||||
break;
|
||||
case 2:
|
||||
angle = -angle;
|
||||
break;
|
||||
case 3:
|
||||
angle = -M_PI + angle;
|
||||
break;
|
||||
case 4:
|
||||
angle = M_PI / 2.0 - angle;
|
||||
break;
|
||||
case 5:
|
||||
angle = M_PI / 2.0 + angle;
|
||||
break;
|
||||
case 6:
|
||||
angle = -M_PI / 2.0 + angle;
|
||||
break;
|
||||
case 7:
|
||||
angle = -M_PI / 2.0 - angle;
|
||||
break;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
#endif // TRIGONOMETRY_TABLE_HPP
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TYPEDEFS_H
|
||||
#define TYPEDEFS_H
|
||||
|
||||
#include <limits>
|
||||
#include <osrm/strong_typedef.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
// Necessary workaround for Windows as VS doesn't implement C99
|
||||
#ifdef _MSC_VER
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// OpenStreetMap node ids are higher than 2^32
|
||||
OSRM_STRONG_TYPEDEF(uint64_t, OSMNodeID)
|
||||
OSRM_STRONG_TYPEDEF(uint32_t, OSMWayID)
|
||||
|
||||
static const OSMNodeID SPECIAL_OSM_NODEID = OSMNodeID(std::numeric_limits<std::uint64_t>::max());
|
||||
static const OSMWayID SPECIAL_OSM_WAYID = OSMWayID(std::numeric_limits<std::uint32_t>::max());
|
||||
|
||||
static const OSMNodeID MAX_OSM_NODEID = OSMNodeID(std::numeric_limits<std::uint64_t>::max());
|
||||
static const OSMNodeID MIN_OSM_NODEID = OSMNodeID(std::numeric_limits<std::uint64_t>::min());
|
||||
static const OSMWayID MAX_OSM_WAYID = OSMWayID(std::numeric_limits<std::uint32_t>::max());
|
||||
static const OSMWayID MIN_OSM_WAYID = OSMWayID(std::numeric_limits<std::uint32_t>::min());
|
||||
|
||||
using OSMNodeID_weak = std::uint64_t;
|
||||
using OSMEdgeID_weak = std::uint64_t;
|
||||
|
||||
using NodeID = unsigned int;
|
||||
using EdgeID = unsigned int;
|
||||
using EdgeWeight = int;
|
||||
|
||||
static const NodeID SPECIAL_NODEID = std::numeric_limits<unsigned>::max();
|
||||
static const EdgeID SPECIAL_EDGEID = std::numeric_limits<unsigned>::max();
|
||||
static const unsigned INVALID_NAMEID = std::numeric_limits<unsigned>::max();
|
||||
static const unsigned INVALID_COMPONENTID = 0;
|
||||
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<int>::max();
|
||||
|
||||
#endif /* TYPEDEFS_H */
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef VERSION_HPP
|
||||
#define VERSION_HPP
|
||||
|
||||
#define OSRM_VERSION_MAJOR "@OSRM_VERSION_MAJOR@"
|
||||
#define OSRM_VERSION_MINOR "@OSRM_VERSION_MINOR@"
|
||||
#define OSRM_VERSION_PATCH "@OSRM_VERSION_PATCH@"
|
||||
|
||||
#define OSRM_VERSION "v" OSRM_VERSION_MAJOR "." OSRM_VERSION_MINOR "." OSRM_VERSION_PATCH
|
||||
|
||||
#endif // VERSION_HPP
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef XML_RENDERER_HPP
|
||||
#define XML_RENDERER_HPP
|
||||
|
||||
#include "cast.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace json
|
||||
{
|
||||
|
||||
struct XMLToArrayRenderer : mapbox::util::static_visitor<>
|
||||
{
|
||||
explicit XMLToArrayRenderer(std::vector<char> &_out) : out(_out) {}
|
||||
|
||||
void operator()(const String &string) const
|
||||
{
|
||||
out.push_back('\"');
|
||||
out.insert(out.end(), string.value.begin(), string.value.end());
|
||||
out.push_back('\"');
|
||||
}
|
||||
|
||||
void operator()(const Number &number) const
|
||||
{
|
||||
const std::string number_string = cast::to_string_with_precision(number.value);
|
||||
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||
}
|
||||
|
||||
void operator()(const Object &object) const
|
||||
{
|
||||
for (auto &&each : object.values)
|
||||
{
|
||||
if (each.first.at(0) != '_')
|
||||
{
|
||||
out.push_back('<');
|
||||
out.insert(out.end(), each.first.begin(), each.first.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
out.push_back(' ');
|
||||
out.insert(out.end(), ++(each).first.begin(), each.first.end());
|
||||
out.push_back('=');
|
||||
}
|
||||
mapbox::util::apply_visitor(XMLToArrayRenderer(out), each.second);
|
||||
if (each.first.at(0) != '_')
|
||||
{
|
||||
out.push_back('/');
|
||||
out.push_back('>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(const Array &array) const
|
||||
{
|
||||
for (auto &&each : array.values)
|
||||
{
|
||||
mapbox::util::apply_visitor(XMLToArrayRenderer(out), each);
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(const True &) const
|
||||
{
|
||||
const std::string temp("true");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
void operator()(const False &) const
|
||||
{
|
||||
const std::string temp("false");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
void operator()(const Null &) const
|
||||
{
|
||||
const std::string temp("null");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char> &out;
|
||||
};
|
||||
|
||||
template <class JSONObject> inline void xml_render(std::vector<char> &out, const JSONObject &object)
|
||||
{
|
||||
Value value = object;
|
||||
mapbox::util::apply_visitor(XMLToArrayRenderer(out), value);
|
||||
}
|
||||
|
||||
template <class JSONObject> inline void gpx_render(std::vector<char> &out, const JSONObject &object)
|
||||
{
|
||||
// add header
|
||||
|
||||
const std::string header{
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><gpx creator=\"OSRM Routing Engine\""
|
||||
" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" xmlns:xsi=\"http:"
|
||||
"//www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topogr"
|
||||
"afix.com/GPX/1/1 gpx.xsd\"><metadata><copyright author=\"Project OSRM\"><lice"
|
||||
"nse>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadat"
|
||||
"a><rte>"};
|
||||
out.insert(out.end(), header.begin(), header.end());
|
||||
|
||||
xml_render(out, object);
|
||||
|
||||
const std::string footer{"</rte></gpx>"};
|
||||
out.insert(out.end(), footer.begin(), footer.end());
|
||||
}
|
||||
} // namespace json
|
||||
} // namespace osrm
|
||||
#endif // XML_RENDERER_HPP
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef XOR_FAST_HASH_HPP
|
||||
#define XOR_FAST_HASH_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
This is an implementation of Tabulation hashing, which has suprising properties like
|
||||
universality.
|
||||
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
|
||||
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
|
||||
|
||||
1: movq table2(%rip), %rdx
|
||||
2: movl %edi, %eax
|
||||
3: movzwl %di, %edi
|
||||
4: shrl $16, %eax
|
||||
5: movzwl %ax, %eax
|
||||
6: movzbl (%rdx,%rax), %eax
|
||||
7: movq table1(%rip), %rdx
|
||||
8: xorb (%rdx,%rdi), %al
|
||||
9: movzbl %al, %eax
|
||||
10: ret
|
||||
|
||||
*/
|
||||
class XORFastHash
|
||||
{ // 65k entries
|
||||
std::vector<unsigned short> table1;
|
||||
std::vector<unsigned short> table2;
|
||||
|
||||
public:
|
||||
XORFastHash()
|
||||
{
|
||||
table1.resize(2 << 16);
|
||||
table2.resize(2 << 16);
|
||||
for (unsigned i = 0; i < (2 << 16); ++i)
|
||||
{
|
||||
table1[i] = static_cast<unsigned short>(i);
|
||||
table2[i] = static_cast<unsigned short>(i);
|
||||
}
|
||||
std::random_shuffle(table1.begin(), table1.end());
|
||||
std::random_shuffle(table2.begin(), table2.end());
|
||||
}
|
||||
|
||||
inline unsigned short operator()(const unsigned originalValue) const
|
||||
{
|
||||
unsigned short lsb = ((originalValue)&0xffff);
|
||||
unsigned short msb = (((originalValue) >> 16) & 0xffff);
|
||||
return table1[lsb] ^ table2[msb];
|
||||
}
|
||||
};
|
||||
|
||||
class XORMiniHash
|
||||
{ // 256 entries
|
||||
std::vector<unsigned char> table1;
|
||||
std::vector<unsigned char> table2;
|
||||
std::vector<unsigned char> table3;
|
||||
std::vector<unsigned char> table4;
|
||||
|
||||
public:
|
||||
XORMiniHash()
|
||||
{
|
||||
table1.resize(1 << 8);
|
||||
table2.resize(1 << 8);
|
||||
table3.resize(1 << 8);
|
||||
table4.resize(1 << 8);
|
||||
for (unsigned i = 0; i < (1 << 8); ++i)
|
||||
{
|
||||
table1[i] = static_cast<unsigned char>(i);
|
||||
table2[i] = static_cast<unsigned char>(i);
|
||||
table3[i] = static_cast<unsigned char>(i);
|
||||
table4[i] = static_cast<unsigned char>(i);
|
||||
}
|
||||
std::random_shuffle(table1.begin(), table1.end());
|
||||
std::random_shuffle(table2.begin(), table2.end());
|
||||
std::random_shuffle(table3.begin(), table3.end());
|
||||
std::random_shuffle(table4.begin(), table4.end());
|
||||
}
|
||||
unsigned char operator()(const unsigned originalValue) const
|
||||
{
|
||||
unsigned char byte1 = ((originalValue)&0xff);
|
||||
unsigned char byte2 = ((originalValue >> 8) & 0xff);
|
||||
unsigned char byte3 = ((originalValue >> 16) & 0xff);
|
||||
unsigned char byte4 = ((originalValue >> 24) & 0xff);
|
||||
return table1[byte1] ^ table2[byte2] ^ table3[byte3] ^ table4[byte4];
|
||||
}
|
||||
};
|
||||
|
||||
#endif // XOR_FAST_HASH_HPP
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef XOR_FAST_HASH_STORAGE_HPP
|
||||
#define XOR_FAST_HASH_STORAGE_HPP
|
||||
|
||||
#include "xor_fast_hash.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
template <typename NodeID, typename Key> class XORFastHashStorage
|
||||
{
|
||||
public:
|
||||
struct HashCell
|
||||
{
|
||||
unsigned time;
|
||||
NodeID id;
|
||||
Key key;
|
||||
HashCell()
|
||||
: time(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
|
||||
key(std::numeric_limits<unsigned>::max())
|
||||
{
|
||||
}
|
||||
|
||||
HashCell(const HashCell &other) : time(other.key), id(other.id), key(other.time) {}
|
||||
|
||||
operator Key() const { return key; }
|
||||
|
||||
void operator=(const Key key_to_insert) { key = key_to_insert; }
|
||||
};
|
||||
|
||||
XORFastHashStorage() = delete;
|
||||
|
||||
explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
|
||||
|
||||
HashCell &operator[](const NodeID node)
|
||||
{
|
||||
unsigned short position = fast_hasher(node);
|
||||
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||
{
|
||||
++position %= (2 << 16);
|
||||
}
|
||||
|
||||
positions[position].time = current_timestamp;
|
||||
positions[position].id = node;
|
||||
return positions[position];
|
||||
}
|
||||
|
||||
// peek into table, get key for node, think of it as a read-only operator[]
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
unsigned short position = fast_hasher(node);
|
||||
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||
{
|
||||
++position %= (2 << 16);
|
||||
}
|
||||
return positions[position].key;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
++current_timestamp;
|
||||
if (std::numeric_limits<unsigned>::max() == current_timestamp)
|
||||
{
|
||||
positions.clear();
|
||||
positions.resize(2 << 16);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<HashCell> positions;
|
||||
XORFastHash fast_hasher;
|
||||
unsigned current_timestamp;
|
||||
};
|
||||
|
||||
#endif // XOR_FAST_HASH_STORAGE_HPP
|
||||
Reference in New Issue
Block a user