renamed: DataStructures/* -> data_structures/*

This commit is contained in:
Dennis Luxen
2014-11-28 12:13:18 +01:00
parent 7b3a0c5105
commit 58de37e822
111 changed files with 489 additions and 356 deletions
+483
View File
@@ -0,0 +1,483 @@
/*
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.
*/
#include <osrm/Coordinate.h>
#include "../Util/MercatorUtil.h"
#ifndef NDEBUG
#include "../Util/simple_logger.hpp"
#endif
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#ifndef NDEBUG
#include <bitset>
#endif
#include <iostream>
#include <limits>
FixedPointCoordinate::FixedPointCoordinate()
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
{
}
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
{
#ifndef NDEBUG
if (0 != (std::abs(lat) >> 30))
{
std::bitset<32> y_coordinate_vector(lat);
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
<< ", bits: " << y_coordinate_vector;
}
if (0 != (std::abs(lon) >> 30))
{
std::bitset<32> x_coordinate_vector(lon);
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
<< ", bits: " << x_coordinate_vector;
}
#endif
}
void FixedPointCoordinate::Reset()
{
lat = std::numeric_limits<int>::min();
lon = std::numeric_limits<int>::min();
}
bool FixedPointCoordinate::isSet() const
{
return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
}
bool FixedPointCoordinate::is_valid() const
{
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
{
return false;
}
return true;
}
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
{
return lat == other.lat && lon == other.lon;
}
double FixedPointCoordinate::ApproximateDistance(const int lat1,
const int lon1,
const int lat2,
const int lon2)
{
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1 / COORDINATE_PRECISION;
double ln1 = lon1 / COORDINATE_PRECISION;
double lt2 = lat2 / COORDINATE_PRECISION;
double ln2 = lon2 / COORDINATE_PRECISION;
double dlat1 = lt1 * (RAD);
double dlong1 = ln1 * (RAD);
double dlat2 = lt2 * (RAD);
double dlong2 = ln2 * (RAD);
double dLong = dlong1 - dlong2;
double dLat = dlat1 - dlat2;
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
const double earth = 6372797.560856;
return earth * cHarv;
}
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
const FixedPointCoordinate &coordinate_2)
{
return ApproximateDistance(
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
}
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
const FixedPointCoordinate &coordinate_2)
{
return ApproximateEuclideanDistance(
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
}
float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
const int lon1,
const int lat2,
const int lon2)
{
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
const float RAD = 0.017453292519943295769236907684886f;
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
const float y_value = float_lat2 - float_lat1;
const float earth_radius = 6372797.560856f;
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
}
float
FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
const FixedPointCoordinate &target_coordinate,
const FixedPointCoordinate &point)
{
// initialize values
const float x_value = static_cast<float>(lat2y(point.lat / COORDINATE_PRECISION));
const float y_value = point.lon / COORDINATE_PRECISION;
float a = static_cast<float>(lat2y(source_coordinate.lat / COORDINATE_PRECISION));
float b = source_coordinate.lon / COORDINATE_PRECISION;
float c = static_cast<float>(lat2y(target_coordinate.lat / COORDINATE_PRECISION));
float d = target_coordinate.lon / COORDINATE_PRECISION;
float p, q;
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
{
const float slope = (d - b) / (c - a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
(1.f + slope * slope);
q = b + slope * (p - a);
}
else
{
p = c;
q = y_value;
}
float ratio;
bool inverse_ratio = false;
// straight line segment on equator
if (std::abs(c) < std::numeric_limits<float>::epsilon() &&
std::abs(a) < std::numeric_limits<float>::epsilon())
{
ratio = (q - b) / (d - b);
}
else
{
if (std::abs(c) < std::numeric_limits<float>::epsilon())
{
// swap start/end
std::swap(a, c);
std::swap(b, d);
inverse_ratio = true;
}
float nY = (d * p - c * q) / (a * d - b * c);
// discretize the result to coordinate precision. it's a hack!
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
{
nY = 0.f;
}
// compute ratio
ratio = (p - nY * a) / c;
}
if (std::isnan(ratio))
{
ratio = (target_coordinate == point ? 1.f : 0.f);
}
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
{
ratio = 0.f;
}
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
{
ratio = 1.f;
}
// we need to do this, if we switched start/end coordinates
if (inverse_ratio)
{
ratio = 1.0f - ratio;
}
// compute the nearest location
FixedPointCoordinate nearest_location;
BOOST_ASSERT(!std::isnan(ratio));
if (ratio <= 0.f)
{ // point is "left" of edge
nearest_location = source_coordinate;
}
else if (ratio >= 1.f)
{ // point is "right" of edge
nearest_location = target_coordinate;
}
else
{ // point lies in between
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
}
BOOST_ASSERT(nearest_location.is_valid());
return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
}
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target,
const FixedPointCoordinate &query_location,
FixedPointCoordinate &nearest_location,
float &ratio)
{
BOOST_ASSERT(query_location.is_valid());
// initialize values
const double x = lat2y(query_location.lat / COORDINATE_PRECISION);
const double y = query_location.lon / COORDINATE_PRECISION;
const double a = lat2y(segment_source.lat / COORDINATE_PRECISION);
const double b = segment_source.lon / COORDINATE_PRECISION;
const double c = lat2y(segment_target.lat / COORDINATE_PRECISION);
const double d = segment_target.lon / COORDINATE_PRECISION;
double p, q /*,mX*/, nY;
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
{
const double m = (d - b) / (c - a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
q = b + m * (p - a);
}
else
{
p = c;
q = y;
}
nY = (d * p - c * q) / (a * d - b * c);
// discretize the result to coordinate precision. it's a hack!
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
{
nY = 0.f;
}
// compute ratio
ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
if (std::isnan(ratio))
{
ratio = (segment_target == query_location ? 1.f : 0.f);
}
else if (std::abs(ratio) <= std::numeric_limits<double>::epsilon())
{
ratio = 0.f;
}
else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::epsilon())
{
ratio = 1.f;
}
// compute nearest location
BOOST_ASSERT(!std::isnan(ratio));
if (ratio <= 0.f)
{
nearest_location = segment_source;
}
else if (ratio >= 1.f)
{
nearest_location = segment_target;
}
else
{
// point lies in between
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
}
BOOST_ASSERT(nearest_location.is_valid());
const float approximate_distance =
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
BOOST_ASSERT(0. <= approximate_distance);
return approximate_distance;
}
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
{
char buffer[12];
buffer[11] = 0; // zero termination
output = printInt<11, 6>(buffer, value);
}
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
std::string &output)
{
std::string tmp;
tmp.reserve(23);
convertInternalLatLonToString(coord.lon, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lat, tmp);
output += tmp;
}
void
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
std::string &output)
{
std::string tmp;
tmp.reserve(23);
convertInternalLatLonToString(coord.lat, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lon, tmp);
output += tmp;
}
void FixedPointCoordinate::Output(std::ostream &out) const
{
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
}
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate &second_coordinate)
{
const float lon_diff =
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
const float lon_delta = DegreeToRadian(lon_diff);
const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION);
const float y = sin(lon_delta) * cos(lat2);
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
float result = RadianToDegree(std::atan2(y, x));
while (result < 0.f)
{
result += 360.f;
}
while (result >= 360.f)
{
result -= 360.f;
}
return result;
}
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
{
const float lon_delta =
DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
const float y_value = std::sin(lon_delta) * std::cos(lat2);
const float x_value =
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
float result = RadianToDegree(std::atan2(y_value, x_value));
while (result < 0.f)
{
result += 360.f;
}
while (result >= 360.f)
{
result -= 360.f;
}
return result;
}
float FixedPointCoordinate::DegreeToRadian(const float degree)
{
return degree * (static_cast<float>(M_PI) / 180.f);
}
float FixedPointCoordinate::RadianToDegree(const float radian)
{
return radian * (180.f * static_cast<float>(M_1_PI));
}
// This distance computation does integer arithmetic only and is a lot faster than
// the other distance function which are numerically correct('ish).
// It preserves some order among the elements that make it useful for certain purposes
int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation(
const FixedPointCoordinate &input_point,
const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target)
{
// initialize values
const float x = static_cast<float>(lat2y(input_point.lat / COORDINATE_PRECISION));
const float y = input_point.lon / COORDINATE_PRECISION;
const float a = static_cast<float>(lat2y(segment_source.lat / COORDINATE_PRECISION));
const float b = segment_source.lon / COORDINATE_PRECISION;
const float c = static_cast<float>(lat2y(segment_target.lat / COORDINATE_PRECISION));
const float d = segment_target.lon / COORDINATE_PRECISION;
float p, q;
if (a == c)
{
p = c;
q = y;
}
else
{
const float m = (d - b) / (c - a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
q = b + m * (p - a);
}
const float nY = (d * p - c * q) / (a * d - b * c);
float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
if (std::isnan(ratio))
{
ratio = (segment_target == input_point) ? 1.f : 0.f;
}
// compute target quasi-location
int dx, dy;
if (ratio < 0.f)
{
dx = input_point.lon - segment_source.lon;
dy = input_point.lat - segment_source.lat;
}
else if (ratio > 1.f)
{
dx = input_point.lon - segment_target.lon;
dy = input_point.lat - segment_target.lat;
}
else
{
// point lies in between
dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
dy = input_point.lat - static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
}
// return an approximation in the plane
return static_cast<int>(sqrt(dx * dx + dy * dy));
}
+123
View File
@@ -0,0 +1,123 @@
/*
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 INPUT_READER_FACTORY_H
#define INPUT_READER_FACTORY_H
#include <boost/assert.hpp>
#include <bzlib.h>
#include <libxml/xmlreader.h>
struct BZ2Context
{
FILE *file;
BZFILE *bz2;
int error;
int nUnused;
char unused[BZ_MAX_UNUSED];
};
int readFromBz2Stream(void *pointer, char *buffer, int len)
{
void *unusedTmpVoid = nullptr;
char *unusedTmp = nullptr;
BZ2Context *context = (BZ2Context *)pointer;
int read = 0;
while (0 == read &&
!(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file)))
{
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
if (BZ_OK == context->error)
{
return read;
}
else if (BZ_STREAM_END == context->error)
{
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused");
unusedTmp = (char *)unusedTmpVoid;
for (int i = 0; i < context->nUnused; i++)
{
context->unused[i] = unusedTmp[i];
}
BZ2_bzReadClose(&context->error, context->bz2);
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose");
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
if (0 == context->nUnused && feof(context->file))
{
return read;
}
else
{
context->bz2 = BZ2_bzReadOpen(
&context->error, context->file, 0, 0, context->unused, context->nUnused);
BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file");
}
}
else
{
BOOST_ASSERT_MSG(false, "Could not read bz2 file");
}
}
return read;
}
int closeBz2Stream(void *pointer)
{
BZ2Context *context = (BZ2Context *)pointer;
fclose(context->file);
delete context;
return 0;
}
xmlTextReaderPtr inputReaderFactory(const char *name)
{
std::string inputName(name);
if (inputName.find(".osm.bz2") != std::string::npos)
{
BZ2Context *context = new BZ2Context();
context->error = false;
context->file = fopen(name, "r");
int error;
context->bz2 =
BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
if (context->bz2 == nullptr || context->file == nullptr)
{
delete context;
return nullptr;
}
return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, nullptr, nullptr, 0);
}
else
{
return xmlNewTextReaderFilename(name);
}
}
#endif // INPUT_READER_FACTORY_H
+290
View File
@@ -0,0 +1,290 @@
/*
Copyright (c) 2014, 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 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>
#include <cstring>
template <typename NodeID, typename Key> class ArrayStorage
{
public:
explicit ArrayStorage(size_t size) : positions(new Key[size])
{
memset(positions, 0, size * sizeof(Key));
}
~ArrayStorage() { delete[] positions; }
Key &operator[](NodeID node) { return positions[node]; }
void Clear() {}
private:
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(); }
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 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[node];
return inserted_nodes[index].data;
}
Data const &GetData(NodeID node) const
{
const Key index = node_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)
{
BOOST_ASSERT(WasInserted(node));
const Key index = node_index[node];
return inserted_nodes[index].key == 0;
}
bool WasInserted(const NodeID node)
{
const Key index = node_index[node];
if (index >= static_cast<Key>(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;
}
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 (typename std::vector<HeapElement>::iterator 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[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(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;
Key nextKey = key << 1;
while (nextKey < static_cast<Key>(heap.size()))
{
const Key nextKeyOther = nextKey + 1;
if ((nextKeyOther < static_cast<Key>(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 (Key i = 2; i < (Key)heap.size(); ++i)
{
BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight);
}
#endif
}
};
#endif // BINARY_HEAP_H
+83
View File
@@ -0,0 +1,83 @@
/*
Copyright (c) 2014, 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 CONCURRENT_QUEUE_HPP
#define CONCURRENT_QUEUE_HPP
#include <boost/circular_buffer.hpp>
#include <condition_variable>
#include <mutex>
template <typename Data> class ConcurrentQueue
{
public:
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) {}
inline void push(const Data &data)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_not_full.wait(lock,
[this]
{ return m_internal_queue.size() < m_internal_queue.capacity(); });
m_internal_queue.push_back(data);
m_not_empty.notify_one();
}
inline bool empty() const { return m_internal_queue.empty(); }
inline void wait_and_pop(Data &popped_value)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_not_empty.wait(lock,
[this]
{ return !m_internal_queue.empty(); });
popped_value = m_internal_queue.front();
m_internal_queue.pop_front();
m_not_full.notify_one();
}
inline bool try_pop(Data &popped_value)
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_internal_queue.empty())
{
return false;
}
popped_value = m_internal_queue.front();
m_internal_queue.pop_front();
m_not_full.notify_one();
return true;
}
private:
boost::circular_buffer<Data> m_internal_queue;
std::mutex m_mutex;
std::condition_variable m_not_empty;
std::condition_variable m_not_full;
};
#endif // CONCURRENT_QUEUE_HPP
+313
View File
@@ -0,0 +1,313 @@
/*
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 DEALLOCATINGVECTOR_H_
#define DEALLOCATINGVECTOR_H_
#include "../Util/integer_range.hpp"
#include <boost/iterator/iterator_facade.hpp>
#include <utility>
#include <vector>
template <typename ElementT> struct DeallocatingVectorIteratorState
{
DeallocatingVectorIteratorState() : index(-1), 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;
inline 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 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 = 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 = DeallocatingVectorIterator<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(); }
inline void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &other)
{
std::swap(current_size, other.current_size);
bucket_list.swap(other.bucket_list);
}
inline 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;
}
inline 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> inline 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;
}
inline void reserve(const std::size_t) const { /* don't do anything */ }
inline 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;
}
inline std::size_t size() const { return current_size; }
inline std::size_t capacity() const { return bucket_list.size() * ELEMENTS_PER_BLOCK; }
inline iterator begin() { return iterator(static_cast<std::size_t>(0), &bucket_list); }
inline iterator end() { return iterator(size(), &bucket_list); }
inline deallocation_iterator dbegin()
{
return deallocation_iterator(static_cast<std::size_t>(0), &bucket_list);
}
inline deallocation_iterator dend() { return deallocation_iterator(size(), &bucket_list); }
inline const_iterator begin() const
{
return const_iterator(static_cast<std::size_t>(0), &bucket_list);
}
inline const_iterator end() const { return const_iterator(size(), &bucket_list); }
inline 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]);
}
const inline 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]);
}
inline ElementT &back()
{
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]);
}
const inline 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>
const inline void append(InputIterator first, const InputIterator last)
{
InputIterator position = first;
while (position != last)
{
push_back(*position);
++position;
}
}
};
#endif /* DEALLOCATINGVECTOR_H_ */
+295
View File
@@ -0,0 +1,295 @@
/*
Copyright (c) 2014, 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 DYNAMICGRAPH_HPP
#define DYNAMICGRAPH_HPP
#include "deallocating_vector.hpp"
#include "../Util/integer_range.hpp"
#include <boost/assert.hpp>
#include <cstdint>
#include <algorithm>
#include <limits>
#include <vector>
#include <atomic>
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 &right) const
{
if (source != right.source)
{
return source < right.source;
}
return target < right.target;
}
};
// Constructs an empty graph with a given number of nodes.
explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0)
{
node_list.reserve(number_of_nodes);
node_list.resize(number_of_nodes);
edge_list.reserve(number_of_nodes * 1.1);
edge_list.resize(number_of_nodes);
}
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
{
number_of_nodes = nodes;
number_of_edges = (EdgeIterator)graph.size();
node_list.reserve(number_of_nodes + 1);
node_list.resize(number_of_nodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for (const auto node : osrm::irange(0u, number_of_nodes))
{
EdgeIterator lastEdge = edge;
while (edge < number_of_edges && graph[edge].source == node)
{
++edge;
}
node_list[node].firstEdge = position;
node_list[node].edges = edge - lastEdge;
position += node_list[node].edges;
}
node_list.back().firstEdge = 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_list[node].firstEdge,
node_list[node].firstEdge + node_list[node].edges))
{
edge_list[i].target = graph[edge].target;
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_list[n].edges; }
unsigned GetDirectedOutDegree(const NodeIterator n) const
{
unsigned degree = 0;
for (const auto edge : osrm::irange(BeginEdges(n), EndEdges(n)))
{
if (GetEdgeData(edge).forward)
{
++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_list[n].firstEdge);
}
EdgeIterator EndEdges(const NodeIterator n) const
{
return EdgeIterator(node_list[n].firstEdge + node_list[n].edges);
}
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
{
return osrm::irange(BeginEdges(node), EndEdges(node));
}
NodeIterator InsertNode()
{
node_list.emplace_back(node_list.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_list[from];
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
if (newFirstEdge >= edge_list.size() || !isDummy(newFirstEdge))
{
if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
{
node.firstEdge--;
edge_list[node.firstEdge] = edge_list[node.firstEdge + 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.firstEdge + i];
makeDummy(node.firstEdge + i);
}
for (const auto i : osrm::irange(node.edges + 1, newSize))
{
makeDummy(newFirstEdge + i);
}
node.firstEdge = newFirstEdge;
}
}
Edge &edge = edge_list[node.firstEdge + node.edges];
edge.target = to;
edge.data = data;
++number_of_edges;
++node.edges;
return EdgeIterator(node.firstEdge + node.edges);
}
// removes an edge. Invalidates edge iterators for the source node
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
{
Node &node = node_list[source];
--number_of_edges;
--node.edges;
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
const unsigned last = node.firstEdge + 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_list[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 EndEdges(from);
}
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 firstEdge;
// 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_list;
DeallocatingVector<Edge> edge_list;
};
#endif // DYNAMICGRAPH_HPP
+125
View File
@@ -0,0 +1,125 @@
/*
Copyright (c) 2014, 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 EDGE_BASED_NODE_HPP
#define EDGE_BASED_NODE_HPP
#include "../data_structures/travel_mode.hpp"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
#include <limits>
struct EdgeBasedNode
{
EdgeBasedNode() :
forward_edge_based_node_id(SPECIAL_NODEID),
reverse_edge_based_node_id(SPECIAL_NODEID),
u(SPECIAL_NODEID),
v(SPECIAL_NODEID),
name_id(0),
forward_weight(INVALID_EDGE_WEIGHT >> 1),
reverse_weight(INVALID_EDGE_WEIGHT >> 1),
forward_offset(0),
reverse_offset(0),
packed_geometry_id(SPECIAL_EDGEID),
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
is_in_tiny_cc(false),
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
{ }
explicit EdgeBasedNode(
NodeID forward_edge_based_node_id,
NodeID reverse_edge_based_node_id,
NodeID u,
NodeID v,
unsigned name_id,
int forward_weight,
int reverse_weight,
int forward_offset,
int reverse_offset,
unsigned packed_geometry_id,
unsigned short fwd_segment_position,
bool belongs_to_tiny_component,
TravelMode forward_travel_mode,
TravelMode backward_travel_mode
) :
forward_edge_based_node_id(forward_edge_based_node_id),
reverse_edge_based_node_id(reverse_edge_based_node_id),
u(u),
v(v),
name_id(name_id),
forward_weight(forward_weight),
reverse_weight(reverse_weight),
forward_offset(forward_offset),
reverse_offset(reverse_offset),
packed_geometry_id(packed_geometry_id),
fwd_segment_position(fwd_segment_position),
is_in_tiny_cc(belongs_to_tiny_component),
forward_travel_mode(forward_travel_mode),
backward_travel_mode(backward_travel_mode)
{
BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
(reverse_edge_based_node_id != SPECIAL_NODEID));
}
static inline FixedPointCoordinate Centroid(const FixedPointCoordinate & a, const FixedPointCoordinate & b)
{
FixedPointCoordinate centroid;
//The coordinates of the midpoint are given by:
centroid.lat = (a.lat + b.lat)/2;
centroid.lon = (a.lon + b.lon)/2;
return centroid;
}
bool IsCompressed() const
{
return packed_geometry_id != SPECIAL_EDGEID;
}
NodeID forward_edge_based_node_id; // needed for edge-expanded graph
NodeID reverse_edge_based_node_id; // needed for edge-expanded graph
NodeID u; // indices into the coordinates array
NodeID v; // indices into the coordinates array
unsigned name_id; // id of the edge name
int forward_weight; // weight of the edge
int reverse_weight; // weight in the other direction (may be different)
int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice
int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
unsigned short fwd_segment_position; // segment id in a compressed geometry
bool is_in_tiny_cc;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
};
#endif //EDGE_BASED_NODE_HPP
+68
View File
@@ -0,0 +1,68 @@
/*
Copyright (c) 2014, 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 "external_memory_node.hpp"
#include <limits>
ExternalMemoryNode::ExternalMemoryNode(
int lat, int lon, unsigned int node_id, bool barrier, bool traffic_lights)
: QueryNode(lat, lon, node_id), barrier(barrier), traffic_lights(traffic_lights)
{
}
ExternalMemoryNode::ExternalMemoryNode() : barrier(false), traffic_lights(false) {}
ExternalMemoryNode ExternalMemoryNode::min_value()
{
return ExternalMemoryNode(0, 0, 0, false, false);
}
ExternalMemoryNode ExternalMemoryNode::max_value()
{
return ExternalMemoryNode(std::numeric_limits<int>::max(),
std::numeric_limits<int>::max(),
std::numeric_limits<unsigned>::max(),
false,
false);
}
bool ExternalMemoryNodeSTXXLCompare::operator()(const ExternalMemoryNode &left,
const ExternalMemoryNode &right) const
{
return left.node_id < right.node_id;
}
ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::max_value()
{
return ExternalMemoryNode::max_value();
}
ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::min_value()
{
return ExternalMemoryNode::min_value();
}
+57
View File
@@ -0,0 +1,57 @@
/*
Copyright (c) 2014, 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 EXTERNAL_MEMORY_NODE_HPP_
#define EXTERNAL_MEMORY_NODE_HPP_
#include "query_node.hpp"
#include <string>
struct ExternalMemoryNode : QueryNode
{
ExternalMemoryNode(int lat, int lon, NodeID id, bool barrier, bool traffic_light);
ExternalMemoryNode();
static ExternalMemoryNode min_value();
static ExternalMemoryNode max_value();
bool barrier;
bool traffic_lights;
};
struct ExternalMemoryNodeSTXXLCompare
{
using value_type = ExternalMemoryNode;
bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const;
value_type max_value();
value_type min_value();
};
#endif /* EXTERNAL_MEMORY_NODE_HPP_ */
+216
View File
@@ -0,0 +1,216 @@
/*
Copyright (c) 2014, 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 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
+100
View File
@@ -0,0 +1,100 @@
/*
Copyright (c) 2014, 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 "hilbert_value.hpp"
#include <osrm/Coordinate.h>
uint64_t HilbertCode::operator()(const FixedPointCoordinate &current_coordinate) const
{
unsigned location[2];
location[0] = current_coordinate.lat + static_cast<int>(90 * COORDINATE_PRECISION);
location[1] = current_coordinate.lon + static_cast<int>(180 * COORDINATE_PRECISION);
TransposeCoordinate(location);
return BitInterleaving(location[0], location[1]);
}
uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const
{
uint64_t result = 0;
for (int8_t index = 31; index >= 0; --index)
{
result |= (latitude >> index) & 1;
result <<= 1;
result |= (longitude >> index) & 1;
if (0 != index)
{
result <<= 1;
}
}
return result;
}
void HilbertCode::TransposeCoordinate(uint32_t *X) const
{
uint32_t M = 1 << (32 - 1), P, Q, t;
int i;
// Inverse undo
for (Q = M; Q > 1; Q >>= 1)
{
P = Q - 1;
for (i = 0; i < 2; ++i)
{
const bool condition = (X[i] & Q);
if (condition)
{
X[0] ^= P; // invert
}
else
{
t = (X[0] ^ X[i]) & P;
X[0] ^= t;
X[i] ^= t;
}
} // exchange
}
// Gray encode
for (i = 1; i < 2; ++i)
{
X[i] ^= X[i - 1];
}
t = 0;
for (Q = M; Q > 1; Q >>= 1)
{
const bool condition = (X[2 - 1] & Q);
if (condition)
{
t ^= Q - 1;
}
} // check if this for loop is wrong
for (i = 0; i < 2; ++i)
{
X[i] ^= t;
}
}
+49
View File
@@ -0,0 +1,49 @@
/*
Copyright (c) 2014, 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 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 &current_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 */
+105
View File
@@ -0,0 +1,105 @@
/*
Copyright (c) 2014, 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 "import_edge.hpp"
#include <boost/assert.hpp>
bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
{
if (source == other.source)
{
if (target == other.target)
{
if (weight == other.weight)
{
return forward && backward && ((!other.forward) || (!other.backward));
}
return weight < other.weight;
}
return target < other.target;
}
return source < other.source;
}
NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
EdgeWeight weight,
bool forward,
bool backward,
bool roundabout,
bool in_tiny_cc,
bool access_restricted,
TravelMode travel_mode,
bool is_split)
: source(source), target(target), name_id(name_id), weight(weight),
forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
access_restricted(access_restricted), is_split(is_split), travel_mode(travel_mode)
{
}
bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
{
if (source == other.source)
{
if (target == other.target)
{
if (weight == other.weight)
{
return forward && backward && ((!other.forward) || (!other.backward));
}
return weight < other.weight;
}
return target < other.target;
}
return source < other.source;
}
template <class EdgeT>
EdgeBasedEdge::EdgeBasedEdge(const EdgeT &other)
: source(other.source), target(other.target), edge_id(other.data.via),
weight(other.data.distance), forward(other.data.forward), backward(other.data.backward)
{
}
/** Default constructor. target and weight are set to 0.*/
EdgeBasedEdge::EdgeBasedEdge()
: source(0), target(0), edge_id(0), weight(0), forward(false), backward(false)
{
}
EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
const NodeID target,
const NodeID edge_id,
const EdgeWeight weight,
const bool forward,
const bool backward)
: source(source), target(target), edge_id(edge_id), weight(weight), forward(forward),
backward(backward)
{
}
+91
View File
@@ -0,0 +1,91 @@
/*
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 IMPORT_EDGE_HPP
#define IMPORT_EDGE_HPP
#include "../data_structures/travel_mode.hpp"
#include "../typedefs.h"
struct NodeBasedEdge
{
bool operator<(const NodeBasedEdge &e) const;
explicit NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
EdgeWeight weight,
bool forward,
bool backward,
bool roundabout,
bool in_tiny_cc,
bool access_restricted,
TravelMode travel_mode,
bool is_split);
NodeID source;
NodeID target;
NodeID name_id;
EdgeWeight weight;
bool forward : 1;
bool backward : 1;
bool roundabout : 1;
bool in_tiny_cc : 1;
bool access_restricted : 1;
bool is_split : 1;
TravelMode travel_mode : 4;
NodeBasedEdge() = delete;
};
struct EdgeBasedEdge
{
public:
bool operator<(const EdgeBasedEdge &e) const;
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &myEdge);
EdgeBasedEdge();
explicit EdgeBasedEdge(const NodeID source,
const NodeID target,
const NodeID edge_id,
const EdgeWeight weight,
const bool forward,
const bool backward);
NodeID source;
NodeID target;
NodeID edge_id;
EdgeWeight weight : 30;
bool forward : 1;
bool backward : 1;
};
using ImportEdge = NodeBasedEdge;
#endif /* IMPORT_EDGE_HPP */
+94
View File
@@ -0,0 +1,94 @@
/*
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.
*/
// based on
// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
#ifndef JSON_CONTAINER_H
#define JSON_CONTAINER_H
#include <variant/variant.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
namespace JSON
{
struct Object;
struct Array;
struct String
{
String() {}
String(const char *value) : value(value) {}
String(const std::string &value) : value(value) {}
std::string value;
};
struct Number
{
Number() {}
Number(double value) : value(static_cast<double>(value)) {}
double value;
};
struct True
{
};
struct False
{
};
struct Null
{
};
using Value = mapbox::util::variant<String,
Number,
mapbox::util::recursive_wrapper<Object>,
mapbox::util::recursive_wrapper<Array>,
True,
False,
Null>;
struct Object
{
std::unordered_map<std::string, Value> values;
};
struct Array
{
std::vector<Value> values;
};
} // namespace JSON
#endif // JSON_CONTAINER_H
+97
View File
@@ -0,0 +1,97 @@
/*
Copyright (c) 2014, 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 LRUCACHE_HPP
#define LRUCACHE_HPP
#include <list>
#include <unordered_map>
template <typename KeyT, typename ValueT> class LRUCache
{
private:
struct CacheEntry
{
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
KeyT key;
ValueT value;
};
unsigned capacity;
std::list<CacheEntry> itemsInCache;
std::unordered_map<KeyT, typename std::list<CacheEntry>::iterator> positionMap;
public:
explicit LRUCache(unsigned c) : capacity(c) {}
bool Holds(KeyT key)
{
if (positionMap.find(key) != positionMap.end())
{
return true;
}
return false;
}
void Insert(const KeyT key, ValueT &value)
{
itemsInCache.push_front(CacheEntry(key, value));
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
if (itemsInCache.size() > capacity)
{
positionMap.erase(itemsInCache.back().key);
itemsInCache.pop_back();
}
}
void Insert(const KeyT key, ValueT value)
{
itemsInCache.push_front(CacheEntry(key, value));
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
if (itemsInCache.size() > capacity)
{
positionMap.erase(itemsInCache.back().key);
itemsInCache.pop_back();
}
}
bool Fetch(const KeyT key, ValueT &result)
{
if (Holds(key))
{
CacheEntry e = *(positionMap.find(key)->second);
result = e.value;
// move to front
itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
positionMap.find(key)->second = itemsInCache.begin();
return true;
}
return false;
}
unsigned Size() const { return itemsInCache.size(); }
};
#endif // LRUCACHE_HPP
+271
View File
@@ -0,0 +1,271 @@
/*
Copyright (c) 2014, 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 NODE_BASED_GRAPH_HPP
#define NODE_BASED_GRAPH_HPP
#include "dynamic_graph.hpp"
#include "import_edge.hpp"
#include "../Util/simple_logger.hpp"
#include <tbb/parallel_sort.h>
#include <memory>
struct NodeBasedEdgeData
{
NodeBasedEdgeData()
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
nameID(std::numeric_limits<unsigned>::max()),
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
roundabout(false), ignore_in_grid(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
int distance;
unsigned edgeBasedNodeID;
unsigned nameID;
bool isAccessRestricted : 1;
bool shortcut : 1;
bool forward : 1;
bool backward : 1;
bool roundabout : 1;
bool ignore_in_grid : 1;
TravelMode travel_mode : 4;
void SwapDirectionFlags()
{
bool temp_flag = forward;
forward = backward;
backward = temp_flag;
}
bool IsEqualTo(const NodeBasedEdgeData &other) const
{
return (forward == other.forward) && (backward == other.backward) &&
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
(travel_mode == other.travel_mode);
}
};
struct SimpleEdgeData
{
SimpleEdgeData() : capacity(0) {}
EdgeWeight capacity;
};
using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
using SimpleNodeBasedDynamicGraph = DynamicGraph<SimpleEdgeData>;
// Factory method to create NodeBasedDynamicGraph from ImportEdges
inline std::shared_ptr<NodeBasedDynamicGraph>
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
{
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
NodeBasedDynamicGraph::InputEdge edge;
for (const ImportEdge &import_edge : input_edge_list)
{
if (import_edge.forward)
{
edge.source = import_edge.source;
edge.target = import_edge.target;
edge.data.forward = import_edge.forward;
edge.data.backward = import_edge.backward;
}
else
{
edge.source = import_edge.target;
edge.target = import_edge.source;
edge.data.backward = import_edge.forward;
edge.data.forward = import_edge.backward;
}
if (edge.source == edge.target)
{
continue;
}
edge.data.distance = (std::max)((int)import_edge.weight, 1);
BOOST_ASSERT(edge.data.distance > 0);
edge.data.shortcut = false;
edge.data.roundabout = import_edge.roundabout;
edge.data.ignore_in_grid = import_edge.in_tiny_cc;
edge.data.nameID = import_edge.name_id;
edge.data.isAccessRestricted = import_edge.access_restricted;
edge.data.travel_mode = import_edge.travel_mode;
edges_list.push_back(edge);
if (!import_edge.is_split)
{
using std::swap; // enable ADL
swap(edge.source, edge.target);
edge.data.SwapDirectionFlags();
edges_list.push_back(edge);
}
}
// remove duplicate edges
tbb::parallel_sort(edges_list.begin(), edges_list.end());
NodeID edge_count = 0;
for (NodeID i = 0; i < edges_list.size(); )
{
const NodeID source = edges_list[i].source;
const NodeID target = edges_list[i].target;
// remove eigenloops
if (source == target)
{
i++;
continue;
}
NodeBasedDynamicGraph::InputEdge forward_edge;
NodeBasedDynamicGraph::InputEdge reverse_edge;
forward_edge = reverse_edge = edges_list[i];
forward_edge.data.forward = reverse_edge.data.backward = true;
forward_edge.data.backward = reverse_edge.data.forward = false;
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
forward_edge.data.distance = reverse_edge.data.distance =
std::numeric_limits<int>::max();
// remove parallel edges
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
{
if (edges_list[i].data.forward)
{
forward_edge.data.distance =
std::min(edges_list[i].data.distance, forward_edge.data.distance);
}
if (edges_list[i].data.backward)
{
reverse_edge.data.distance =
std::min(edges_list[i].data.distance, reverse_edge.data.distance);
}
++i;
}
// merge edges (s,t) and (t,s) into bidirectional edge
if (forward_edge.data.distance == reverse_edge.data.distance)
{
if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
{
forward_edge.data.backward = true;
edges_list[edge_count++] = forward_edge;
}
}
else
{ // insert seperate edges
if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
{
edges_list[edge_count++] = forward_edge;
}
if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
{
edges_list[edge_count++] = reverse_edge;
}
}
}
edges_list.resize(edge_count);
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
auto graph = std::make_shared<NodeBasedDynamicGraph>(static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
return graph;
}
template<class SimpleEdgeT>
inline std::shared_ptr<SimpleNodeBasedDynamicGraph>
SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdgeT> &input_edge_list)
{
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
tbb::parallel_sort(input_edge_list.begin(), input_edge_list.end());
DeallocatingVector<SimpleNodeBasedDynamicGraph::InputEdge> edges_list;
SimpleNodeBasedDynamicGraph::InputEdge edge;
edge.data.capacity = 1;
for (const SimpleEdgeT &import_edge : input_edge_list)
{
if (import_edge.source == import_edge.target)
{
continue;
}
edge.source = import_edge.source;
edge.target = import_edge.target;
edges_list.push_back(edge);
std::swap(edge.source, edge.target);
edges_list.push_back(edge);
}
// remove duplicate edges
tbb::parallel_sort(edges_list.begin(), edges_list.end());
NodeID edge_count = 0;
for (NodeID i = 0; i < edges_list.size(); )
{
const NodeID source = edges_list[i].source;
const NodeID target = edges_list[i].target;
// remove eigenloops
if (source == target)
{
i++;
continue;
}
SimpleNodeBasedDynamicGraph::InputEdge forward_edge;
SimpleNodeBasedDynamicGraph::InputEdge reverse_edge;
forward_edge = reverse_edge = edges_list[i];
forward_edge.data.capacity = reverse_edge.data.capacity = INVALID_EDGE_WEIGHT;
// remove parallel edges
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
{
forward_edge.data.capacity = std::min(edges_list[i].data.capacity, forward_edge.data.capacity);
reverse_edge.data.capacity = std::min(edges_list[i].data.capacity, reverse_edge.data.capacity);
++i;
}
// merge edges (s,t) and (t,s) into bidirectional edge
if (forward_edge.data.capacity == reverse_edge.data.capacity)
{
if ((int)forward_edge.data.capacity != INVALID_EDGE_WEIGHT)
{
edges_list[edge_count++] = forward_edge;
}
}
else
{ // insert seperate edges
if (((int)forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
{
edges_list[edge_count++] = forward_edge;
}
if ((int)reverse_edge.data.capacity != INVALID_EDGE_WEIGHT)
{
edges_list[edge_count++] = reverse_edge;
}
}
}
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
auto graph = std::make_shared<SimpleNodeBasedDynamicGraph>(number_of_nodes, edges_list);
return graph;
}
#endif // NODE_BASED_GRAPH_HPP
+41
View File
@@ -0,0 +1,41 @@
/*
Copyright (c) 2014, 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 NODE_ID_HPP
#define NODE_ID_HPP
#include "../typedefs.h"
struct Cmp
{
using value_type = NodeID;
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
value_type max_value() { return 0xffffffff; }
value_type min_value() { return 0x0; }
};
#endif // NODE_ID_HPP
+64
View File
@@ -0,0 +1,64 @@
/*
Copyright (c) 2014, 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 ORIGINAL_EDGE_DATA_HPP
#define ORIGINAL_EDGE_DATA_HPP
#include "travel_mode.hpp"
#include "turn_instructions.hpp"
#include "../typedefs.h"
#include <limits>
struct OriginalEdgeData
{
explicit OriginalEdgeData(NodeID via_node,
unsigned name_id,
TurnInstruction turn_instruction,
bool compressed_geometry,
TravelMode travel_mode)
: via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
compressed_geometry(compressed_geometry), travel_mode(travel_mode)
{
}
OriginalEdgeData()
: via_node(std::numeric_limits<unsigned>::max()),
name_id(std::numeric_limits<unsigned>::max()),
turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false),
travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
NodeID via_node;
unsigned name_id;
TurnInstruction turn_instruction;
bool compressed_geometry;
TravelMode travel_mode;
};
#endif // ORIGINAL_EDGE_DATA_HPP
+101
View File
@@ -0,0 +1,101 @@
/*
Copyright (c) 2014, 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 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 / (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
+117
View File
@@ -0,0 +1,117 @@
/*
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.
*/
#include "phantom_node.hpp"
PhantomNode::PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id,
int forward_weight, int reverse_weight, int forward_offset, int reverse_offset,
unsigned packed_geometry_id, FixedPointCoordinate &location,
unsigned short fwd_segment_position,
TravelMode forward_travel_mode, TravelMode backward_travel_mode) :
forward_node_id(forward_node_id),
reverse_node_id(reverse_node_id),
name_id(name_id),
forward_weight(forward_weight),
reverse_weight(reverse_weight),
forward_offset(forward_offset),
reverse_offset(reverse_offset),
packed_geometry_id(packed_geometry_id),
location(location),
fwd_segment_position(fwd_segment_position),
forward_travel_mode(forward_travel_mode),
backward_travel_mode(backward_travel_mode)
{ }
PhantomNode::PhantomNode() :
forward_node_id(SPECIAL_NODEID),
reverse_node_id(SPECIAL_NODEID),
name_id(std::numeric_limits<unsigned>::max()),
forward_weight(INVALID_EDGE_WEIGHT),
reverse_weight(INVALID_EDGE_WEIGHT),
forward_offset(0),
reverse_offset(0),
packed_geometry_id(SPECIAL_EDGEID),
fwd_segment_position(0),
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
{ }
int PhantomNode::GetForwardWeightPlusOffset() const
{
if (SPECIAL_NODEID == forward_node_id)
{
return 0;
}
return forward_offset + forward_weight;
}
int PhantomNode::GetReverseWeightPlusOffset() const
{
if (SPECIAL_NODEID == reverse_node_id)
{
return 0;
}
return reverse_offset + reverse_weight;
}
bool PhantomNode::is_bidirected() const
{
return (forward_node_id != SPECIAL_NODEID) &&
(reverse_node_id != SPECIAL_NODEID);
}
bool PhantomNode::is_compressed() const
{
return (forward_offset != 0) || (reverse_offset != 0);
}
bool PhantomNode::is_valid(const unsigned number_of_nodes) const
{
return
location.is_valid() &&
(
(forward_node_id < number_of_nodes) ||
(reverse_node_id < number_of_nodes)
) &&
(
(forward_weight != INVALID_EDGE_WEIGHT) ||
(reverse_weight != INVALID_EDGE_WEIGHT)
) &&
(name_id != INVALID_NAMEID
);
}
bool PhantomNode::is_valid() const
{
return location.is_valid() &&
(name_id != INVALID_NAMEID);
}
bool PhantomNode::operator==(const PhantomNode & other) const
{
return location == other.location;
}
+112
View File
@@ -0,0 +1,112 @@
/*
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 PHANTOM_NODES_H
#define PHANTOM_NODES_H
#include <osrm/Coordinate.h>
#include "../data_structures/travel_mode.hpp"
#include "../typedefs.h"
#include <iostream>
#include <vector>
struct PhantomNode
{
PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id,
int forward_weight, int reverse_weight, int forward_offset, int reverse_offset,
unsigned packed_geometry_id, FixedPointCoordinate &location,
unsigned short fwd_segment_position,
TravelMode forward_travel_mode, TravelMode backward_travel_mode);
PhantomNode();
NodeID forward_node_id;
NodeID reverse_node_id;
unsigned name_id;
int forward_weight;
int reverse_weight;
int forward_offset;
int reverse_offset;
unsigned packed_geometry_id;
FixedPointCoordinate location;
unsigned short fwd_segment_position;
TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4;
int GetForwardWeightPlusOffset() const;
int GetReverseWeightPlusOffset() const;
bool is_bidirected() const;
bool is_compressed() const;
bool is_valid(const unsigned numberOfNodes) const;
bool is_valid() const;
bool operator==(const PhantomNode & other) const;
};
using PhantomNodeArray = std::vector<std::vector<PhantomNode>>;
struct PhantomNodeLists
{
std::vector<PhantomNode> source_phantom_list;
std::vector<PhantomNode> target_phantom_list;
};
struct PhantomNodes
{
PhantomNode source_phantom;
PhantomNode target_phantom;
};
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
{
out << "source_coord: " << pn.source_phantom.location << "\n";
out << "target_coord: " << pn.target_phantom.location << std::endl;
return out;
}
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn)
{
out << "node1: " << pn.forward_node_id << ", " <<
"node2: " << pn.reverse_node_id << ", " <<
"name: " << pn.name_id << ", " <<
"fwd-w: " << pn.forward_weight << ", " <<
"rev-w: " << pn.reverse_weight << ", " <<
"fwd-o: " << pn.forward_offset << ", " <<
"rev-o: " << pn.reverse_offset << ", " <<
"geom: " << pn.packed_geometry_id << ", " <<
"pos: " << pn.fwd_segment_position << ", " <<
"loc: " << pn.location;
return out;
}
#endif // PHANTOM_NODES_H
+81
View File
@@ -0,0 +1,81 @@
/*
Copyright (c) 2014, 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 QUERYEDGE_HPP_
#define QUERYEDGE_HPP_
#include "../typedefs.h"
struct QueryEdge
{
NodeID source;
NodeID target;
struct EdgeData
{
EdgeData() : id(0), shortcut(false), distance(0), forward(false), backward(false) {}
template <class OtherT> EdgeData(const OtherT &other)
{
distance = other.distance;
shortcut = other.shortcut;
id = other.id;
forward = other.forward;
backward = other.backward;
}
NodeID id : 31;
bool shortcut : 1;
int distance : 30;
bool forward : 1;
bool backward : 1;
} data;
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
QueryEdge(NodeID source, NodeID target, EdgeData data)
: source(source), target(target), data(data)
{
}
bool operator<(const QueryEdge &right) const
{
if (source != right.source)
{
return source < right.source;
}
return target < right.target;
}
bool operator==(const QueryEdge &right) const
{
return (source == right.source && target == right.target &&
data.distance == right.data.distance && data.shortcut == right.data.shortcut &&
data.forward == right.data.forward && data.backward == right.data.backward &&
data.id == right.data.id);
}
};
#endif /* QUERYEDGE_HPP_ */
+85
View File
@@ -0,0 +1,85 @@
/*
Copyright (c) 2014, 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 QUERY_NODE_HPP
#define QUERY_NODE_HPP
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
#include <limits>
struct QueryNode
{
using key_type = NodeID; // type of NodeID
using value_type = int; // type of lat,lons
explicit QueryNode(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
QueryNode()
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
node_id(std::numeric_limits<unsigned>::max())
{
}
int lat;
int lon;
NodeID node_id;
static QueryNode min_value()
{
return QueryNode(static_cast<int>(-90 * COORDINATE_PRECISION),
static_cast<int>(-180 * COORDINATE_PRECISION),
std::numeric_limits<NodeID>::min());
}
static QueryNode max_value()
{
return QueryNode(static_cast<int>(90 * COORDINATE_PRECISION),
static_cast<int>(180 * COORDINATE_PRECISION),
std::numeric_limits<NodeID>::max());
}
value_type operator[](const std::size_t n) const
{
switch (n)
{
case 1:
return lat;
case 0:
return lon;
default:
break;
}
BOOST_ASSERT_MSG(false, "should not happen");
return std::numeric_limits<unsigned>::max();
}
};
#endif // QUERY_NODE_HPP
+258
View File
@@ -0,0 +1,258 @@
/*
Copyright (c) 2014, 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 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 <vector>
#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
explicit RangeTable(const std::vector<unsigned>& 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
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright (c) 2014, 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 RAW_ROUTE_DATA_HPP
#define RAW_ROUTE_DATA_HPP
#include "../data_structures/phantom_node.hpp"
#include "../data_structures/travel_mode.hpp"
#include "../data_structures/turn_instructions.hpp"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <vector>
struct PathData
{
PathData()
: node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT),
segment_duration(INVALID_EDGE_WEIGHT),
turn_instruction(TurnInstruction::NoTurn),
travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
PathData(NodeID node,
unsigned name_id,
TurnInstruction turn_instruction,
EdgeWeight segment_duration,
TravelMode travel_mode)
: node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction),
travel_mode(travel_mode)
{
}
NodeID node;
unsigned name_id;
EdgeWeight segment_duration;
TurnInstruction turn_instruction;
TravelMode travel_mode : 4;
};
struct RawRouteData
{
std::vector<std::vector<PathData>> unpacked_path_segments;
std::vector<PathData> unpacked_alternative;
std::vector<PhantomNodes> segment_end_coordinates;
std::vector<bool> source_traversed_in_reverse;
std::vector<bool> target_traversed_in_reverse;
std::vector<bool> alt_source_traversed_in_reverse;
std::vector<bool> alt_target_traversed_in_reverse;
int shortest_path_length;
int alternative_path_length;
bool is_via_leg(const std::size_t leg) const
{
return (leg != unpacked_path_segments.size() - 1);
}
RawRouteData() :
shortest_path_length(INVALID_EDGE_WEIGHT),
alternative_path_length(INVALID_EDGE_WEIGHT)
{
}
};
#endif // RAW_ROUTE_DATA_HPP
+199
View File
@@ -0,0 +1,199 @@
/*
Copyright (c) 2014, 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 RECTANGLE_HPP
#define RECTANGLE_HPP
#include <boost/assert.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;
inline 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());
}
inline 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;
}
inline 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));
}
inline 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 = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon));
break;
case SOUTH:
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon));
break;
case WEST:
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon));
break;
case EAST:
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon));
break;
case NORTH_EAST:
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon));
break;
case NORTH_WEST:
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon));
break;
case SOUTH_EAST:
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon));
break;
case SOUTH_WEST:
min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon));
break;
default:
break;
}
BOOST_ASSERT(min_dist != std::numeric_limits<float>::max());
return min_dist;
}
inline 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(
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left),
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right)));
min_max_dist = std::min(
min_max_dist,
std::max(
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_right),
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right)));
min_max_dist = std::min(
min_max_dist,
std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_right),
FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left)));
min_max_dist = std::min(
min_max_dist,
std::max(FixedPointCoordinate::ApproximateEuclideanDistance(location, lower_left),
FixedPointCoordinate::ApproximateEuclideanDistance(location, upper_left)));
return min_max_dist;
}
inline 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;
}
inline friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect)
{
out << rect.min_lat / COORDINATE_PRECISION << "," << rect.min_lon / COORDINATE_PRECISION
<< " " << rect.max_lat / COORDINATE_PRECISION << ","
<< rect.max_lon / COORDINATE_PRECISION;
return out;
}
};
#endif
+132
View File
@@ -0,0 +1,132 @@
/*
Copyright (c) 2014, 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 RESTRICTION_HPP
#define RESTRICTION_HPP
#include "../typedefs.h"
#include <limits>
struct TurnRestriction
{
union WayOrNode
{
NodeID node;
EdgeID way;
};
WayOrNode via;
WayOrNode from;
WayOrNode to;
struct Bits
{ // mostly unused
Bits()
: is_only(false), uses_via_way(false), unused2(false), unused3(false), unused4(false),
unused5(false), unused6(false), unused7(false)
{
}
bool is_only : 1;
bool uses_via_way : 1;
bool unused2 : 1;
bool unused3 : 1;
bool unused4 : 1;
bool unused5 : 1;
bool unused6 : 1;
bool unused7 : 1;
} flags;
explicit TurnRestriction(NodeID node)
{
via.node = node;
from.node = SPECIAL_NODEID;
to.node = SPECIAL_NODEID;
}
explicit TurnRestriction(const bool is_only = false)
{
via.node = SPECIAL_NODEID;
from.node = SPECIAL_NODEID;
to.node = SPECIAL_NODEID;
flags.is_only = is_only;
}
};
struct InputRestrictionContainer
{
// EdgeID fromWay;
// EdgeID toWay;
// NodeID via_node;
TurnRestriction restriction;
InputRestrictionContainer(EdgeID fromWay, EdgeID toWay, EdgeID vw)
{
restriction.from.way = fromWay;
restriction.to.way = toWay;
restriction.via.way = vw;
}
explicit InputRestrictionContainer(bool is_only = false)
{
restriction.from.way = SPECIAL_EDGEID;
restriction.to.way = SPECIAL_EDGEID;
restriction.via.node = SPECIAL_NODEID;
restriction.flags.is_only = is_only;
}
static InputRestrictionContainer min_value() { return InputRestrictionContainer(0, 0, 0); }
static InputRestrictionContainer max_value()
{
return InputRestrictionContainer(SPECIAL_EDGEID, SPECIAL_EDGEID, SPECIAL_EDGEID);
}
};
struct CmpRestrictionContainerByFrom
{
typedef InputRestrictionContainer value_type;
inline bool operator()(const InputRestrictionContainer &a,
const InputRestrictionContainer &b) const
{
return a.restriction.from.way < b.restriction.from.way;
}
inline value_type max_value() const { return InputRestrictionContainer::max_value(); }
inline value_type min_value() const { return InputRestrictionContainer::min_value(); }
};
struct CmpRestrictionContainerByTo
{
typedef InputRestrictionContainer value_type;
inline bool operator()(const InputRestrictionContainer &a,
const InputRestrictionContainer &b) const
{
return a.restriction.to.way < b.restriction.to.way;
}
value_type max_value() const { return InputRestrictionContainer::max_value(); }
value_type min_value() const { return InputRestrictionContainer::min_value(); }
};
#endif // RESTRICTION_HPP
+218
View File
@@ -0,0 +1,218 @@
/*
Copyright (c) 2014, 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 "restriction_map.hpp"
bool RestrictionMap::IsViaNode(const NodeID node) const
{
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
}
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
const std::vector<TurnRestriction> &restriction_list)
: m_count(0), m_graph(graph)
{
// decompose restriction consisting of a start, via and end node into a
// a pair of starting edge and a list of all end nodes
for (auto &restriction : restriction_list)
{
m_restriction_start_nodes.insert(restriction.from.node);
m_no_turn_via_node_set.insert(restriction.via.node);
RestrictionSource restriction_source = {restriction.from.node, restriction.via.node};
unsigned index;
auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter == m_restriction_map.end())
{
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index + 1);
m_restriction_map.emplace(restriction_source, index);
}
else
{
index = restriction_iter->second;
// Map already contains an is_only_*-restriction
if (m_restriction_bucket_list.at(index).begin()->is_only)
{
continue;
}
else if (restriction.flags.is_only)
{
// We are going to insert an is_only_*-restriction. There can be only one.
m_count -= m_restriction_bucket_list.at(index).size();
m_restriction_bucket_list.at(index).clear();
}
}
++m_count;
m_restriction_bucket_list.at(index)
.emplace_back(restriction.to.node, restriction.flags.is_only);
}
}
// Replace end v with w in each turn restriction containing u as via node
void RestrictionMap::FixupArrivingTurnRestriction(const NodeID node_u,
const NodeID node_v,
const NodeID node_w)
{
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
if (!IsViaNode(node_u))
{
return;
}
// find all potential start edges. It is more efficent to get a (small) list
// of potential start edges than iterating over all buckets
std::vector<NodeID> predecessors;
for (const EdgeID current_edge_id : m_graph->GetAdjacentEdgeRange(node_u))
{
const NodeID target = m_graph->GetTarget(current_edge_id);
if (node_v != target)
{
predecessors.push_back(target);
}
}
for (const NodeID node_x : predecessors)
{
const auto restriction_iterator = m_restriction_map.find({node_x, node_u});
if (restriction_iterator == m_restriction_map.end())
{
continue;
}
const unsigned index = restriction_iterator->second;
auto &bucket = m_restriction_bucket_list.at(index);
for (RestrictionTarget &restriction_target : bucket)
{
if (node_v == restriction_target.target_node)
{
restriction_target.target_node = node_w;
}
}
}
}
// Replaces start edge (v, w) with (u, w). Only start node changes.
void RestrictionMap::FixupStartingTurnRestriction(const NodeID node_u,
const NodeID node_v,
const NodeID node_w)
{
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
if (!IsSourceNode(node_v))
{
return;
}
const auto restriction_iterator = m_restriction_map.find({node_v, node_w});
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second;
// remove old restriction start (v,w)
m_restriction_map.erase(restriction_iterator);
m_restriction_start_nodes.emplace(node_u);
// insert new restriction start (u,w) (pointing to index)
RestrictionSource new_source = {node_u, node_w};
m_restriction_map.emplace(new_source, index);
}
}
// Check if edge (u, v) is the start of any turn restriction.
// If so returns id of first target node.
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const
{
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
if (!IsSourceNode(node_u))
{
return SPECIAL_NODEID;
}
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
const auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionTarget &restriction_target : bucket)
{
if (restriction_target.is_only)
{
return restriction_target.target_node;
}
}
}
return SPECIAL_NODEID;
}
// Checks if turn <u,v,w> is actually a turn restriction.
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
const NodeID node_v,
const NodeID node_w) const
{
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
if (!IsSourceNode(node_u))
{
return false;
}
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
const auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionTarget &restriction_target : bucket)
{
if ((node_w == restriction_target.target_node) && // target found
(!restriction_target.is_only) // and not an only_-restr.
)
{
return true;
}
}
}
return false;
}
// check of node is the start of any restriction
bool RestrictionMap::IsSourceNode(const NodeID node) const
{
if (m_restriction_start_nodes.find(node) == m_restriction_start_nodes.end())
{
return false;
}
return true;
}
+125
View File
@@ -0,0 +1,125 @@
/*
Copyright (c) 2014, 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 RESTRICTION_MAP_HPP
#define RESTRICTION_MAP_HPP
#include <memory>
#include "node_based_graph.hpp"
#include "restriction.hpp"
#include "../Util/StdHashExtensions.h"
#include "../typedefs.h"
#include <unordered_map>
#include <unordered_set>
struct RestrictionSource
{
NodeID start_node;
NodeID via_node;
RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via)
{
}
friend inline bool operator==(const RestrictionSource &lhs, const RestrictionSource &rhs)
{
return (lhs.start_node == rhs.start_node && lhs.via_node == rhs.via_node);
}
};
struct RestrictionTarget
{
NodeID target_node;
bool is_only;
explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only)
{
}
friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs)
{
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
}
};
namespace std
{
template <> struct hash<RestrictionSource>
{
size_t operator()(const RestrictionSource &r_source) const
{
return hash_val(r_source.start_node, r_source.via_node);
}
};
template <> struct hash<RestrictionTarget>
{
size_t operator()(const RestrictionTarget &r_target) const
{
return hash_val(r_target.target_node, r_target.is_only);
}
};
}
/**
\brief Efficent look up if an edge is the start + via node of a TurnRestriction
EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
*/
class RestrictionMap
{
public:
RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
const std::vector<TurnRestriction> &input_restrictions_list);
void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
bool IsViaNode(const NodeID node) const;
std::size_t size()
{
return m_count;
}
private:
bool IsSourceNode(const NodeID node) const;
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
using EdgeData = NodeBasedDynamicGraph::EdgeData;
std::size_t m_count;
std::shared_ptr<NodeBasedDynamicGraph> m_graph;
//! index -> list of (target, isOnly)
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
//! maps (start, via) -> bucket index
std::unordered_map<RestrictionSource, unsigned> m_restriction_map;
std::unordered_set<NodeID> m_restriction_start_nodes;
std::unordered_set<NodeID> m_no_turn_via_node_set;
};
#endif //RESTRICTION_MAP_HPP
+117
View File
@@ -0,0 +1,117 @@
/*
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.
*/
#include <osrm/RouteParameters.h>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/include/at_c.hpp>
RouteParameters::RouteParameters()
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
compression(true), deprecatedAPI(false), uturn_default(false), check_sum(-1), num_results(1)
{
}
void RouteParameters::setZoomLevel(const short level)
{
if (18 >= level && 0 <= level)
{
zoom_level = level;
}
}
void RouteParameters::setNumberOfResults(const short number)
{
if (number > 0 && number <= 100)
{
num_results = number;
}
}
void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }
void RouteParameters::setUTurn(const bool flag)
{
uturns.resize(coordinates.size(), uturn_default);
if (!uturns.empty())
{
uturns.back() = flag;
}
}
void RouteParameters::setAllUTurns(const bool flag)
{
// if the flag flips the default, then we erase everything.
if (flag)
{
uturn_default = flag;
uturns.clear();
uturns.resize(coordinates.size(), uturn_default);
}
}
void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }
void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }
void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = flag; }
void RouteParameters::setService(const std::string &service_string) { service = service_string; }
void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
void RouteParameters::setJSONpParameter(const std::string &parameter)
{
jsonp_parameter = parameter;
}
void RouteParameters::addHint(const std::string &hint)
{
hints.resize(coordinates.size());
if (!hints.empty())
{
hints.back() = hint;
}
}
void RouteParameters::setLanguage(const std::string &language_string)
{
language = language_string;
}
void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
void
RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
{
coordinates.emplace_back(
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
}
+60
View File
@@ -0,0 +1,60 @@
/*
Copyright (c) 2014, 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 SEARCH_ENGINE_HPP
#define SEARCH_ENGINE_HPP
#include "search_engine_data.hpp"
#include "../RoutingAlgorithms/AlternativePathRouting.h"
#include "../RoutingAlgorithms/ManyToManyRouting.h"
#include "../RoutingAlgorithms/ShortestPathRouting.h"
#include <type_traits>
template <class DataFacadeT> class SearchEngine
{
private:
DataFacadeT *facade;
SearchEngineData engine_working_data;
public:
ShortestPathRouting<DataFacadeT> shortest_path;
AlternativeRouting<DataFacadeT> alternative_path;
ManyToManyRouting<DataFacadeT> distance_table;
explicit SearchEngine(DataFacadeT *facade)
: facade(facade), shortest_path(facade, engine_working_data),
alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
{
static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
static_assert(std::is_object<DataFacadeT>::value, "don't instantiate with void, function, or reference");
}
~SearchEngine() {}
};
#endif // SEARCH_ENGINE_HPP
+93
View File
@@ -0,0 +1,93 @@
/*
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.
*/
#include "search_engine_data.hpp"
#include "binary_heap.hpp"
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
{
if (forwardHeap.get())
{
forwardHeap->Clear();
}
else
{
forwardHeap.reset(new QueryHeap(number_of_nodes));
}
if (backwardHeap.get())
{
backwardHeap->Clear();
}
else
{
backwardHeap.reset(new QueryHeap(number_of_nodes));
}
}
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
{
if (forwardHeap2.get())
{
forwardHeap2->Clear();
}
else
{
forwardHeap2.reset(new QueryHeap(number_of_nodes));
}
if (backwardHeap2.get())
{
backwardHeap2->Clear();
}
else
{
backwardHeap2.reset(new QueryHeap(number_of_nodes));
}
}
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
{
if (forwardHeap3.get())
{
forwardHeap3->Clear();
}
else
{
forwardHeap3.reset(new QueryHeap(number_of_nodes));
}
if (backwardHeap3.get())
{
backwardHeap3->Clear();
}
else
{
backwardHeap3.reset(new QueryHeap(number_of_nodes));
}
}
+61
View File
@@ -0,0 +1,61 @@
/*
Copyright (c) 2014, 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 SEARCH_ENGINE_DATA_HPP
#define SEARCH_ENGINE_DATA_HPP
#include <boost/thread/tss.hpp>
#include "../typedefs.h"
#include "binary_heap.hpp"
struct HeapData
{
NodeID parent;
/* explicit */ HeapData(NodeID p) : parent(p) {}
};
struct SearchEngineData
{
using QueryHeap = BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
static SearchEngineHeapPtr forwardHeap;
static SearchEngineHeapPtr backwardHeap;
static SearchEngineHeapPtr forwardHeap2;
static SearchEngineHeapPtr backwardHeap2;
static SearchEngineHeapPtr forwardHeap3;
static SearchEngineHeapPtr backwardHeap3;
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
};
#endif // SEARCH_ENGINE_DATA_HPP
+78
View File
@@ -0,0 +1,78 @@
/*
Copyright (c) 2014, 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 SEGMENT_INFORMATION_H
#define SEGMENT_INFORMATION_H
#include "turn_instructions.hpp"
#include "../data_structures/travel_mode.hpp"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
// Struct fits everything in one cache line
struct SegmentInformation
{
FixedPointCoordinate location;
NodeID name_id;
EdgeWeight duration;
float length;
short bearing; // more than enough [0..3600] fits into 12 bits
TurnInstruction turn_instruction;
TravelMode travel_mode;
bool necessary;
bool is_via_location;
explicit SegmentInformation(const FixedPointCoordinate &location,
const NodeID name_id,
const EdgeWeight duration,
const float length,
const TurnInstruction turn_instruction,
const bool necessary,
const bool is_via_location,
const TravelMode travel_mode)
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
turn_instruction(turn_instruction), travel_mode(travel_mode), necessary(necessary),
is_via_location(is_via_location)
{
}
explicit SegmentInformation(const FixedPointCoordinate &location,
const NodeID name_id,
const EdgeWeight duration,
const float length,
const TurnInstruction turn_instruction,
const TravelMode travel_mode)
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
turn_instruction(turn_instruction), travel_mode(travel_mode),
necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false)
{
}
};
#endif /* SEGMENT_INFORMATION_H */
+371
View File
@@ -0,0 +1,371 @@
/*
Copyright (c) 2014, 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 SHARED_MEMORY_FACTORY_HPP
#define SHARED_MEMORY_FACTORY_HPP
#include "../Util/OSRMException.h"
#include "../Util/simple_logger.hpp"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/interprocess/mapped_region.hpp>
#ifndef WIN32
#include <boost/interprocess/xsi_shared_memory.hpp>
#else
#include <boost/interprocess/shared_memory_object.hpp>
#endif
#ifdef __linux__
#include <sys/ipc.h>
#include <sys/shm.h>
#endif
// #include <cstring>
#include <cstdint>
#include <algorithm>
#include <exception>
struct OSRMLockFile
{
boost::filesystem::path operator()()
{
boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path();
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
return lock_file;
}
};
#ifndef WIN32
class SharedMemory
{
// Remove shared memory on destruction
class shm_remove
{
private:
int m_shmid;
bool m_initialized;
public:
void SetID(int shmid)
{
m_shmid = shmid;
m_initialized = true;
}
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
shm_remove(const shm_remove &) = delete;
~shm_remove()
{
if (m_initialized)
{
SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
if (!boost::interprocess::xsi_shared_memory::remove(m_shmid))
{
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
}
}
}
};
public:
void *Ptr() const { return region.get_address(); }
SharedMemory() = delete;
SharedMemory(const SharedMemory &) = delete;
template <typename IdentifierT>
SharedMemory(const boost::filesystem::path &lock_file,
const IdentifierT id,
const uint64_t size = 0,
bool read_write = false,
bool remove_prev = true)
: key(lock_file.string().c_str(), id)
{
if (0 == size)
{ // read_only
shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_only, key);
region = boost::interprocess::mapped_region(
shm,
(read_write ? boost::interprocess::read_write : boost::interprocess::read_only));
}
else
{ // writeable pointer
// remove previously allocated mem
if (remove_prev)
{
Remove(key);
}
shm = boost::interprocess::xsi_shared_memory(
boost::interprocess::open_or_create, key, size);
#ifdef __linux__
if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, 0))
{
if (ENOMEM == errno)
{
SimpleLogger().Write(logWARNING) << "could not lock shared memory to RAM";
}
}
#endif
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
remover.SetID(shm.get_shmid());
SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
}
}
template <typename IdentifierT> static bool RegionExists(const IdentifierT id)
{
bool result = true;
try
{
OSRMLockFile lock_file;
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
result = RegionExists(key);
}
catch (...) { result = false; }
return result;
}
template <typename IdentifierT> static bool Remove(const IdentifierT id)
{
OSRMLockFile lock_file;
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
return Remove(key);
}
private:
static bool RegionExists(const boost::interprocess::xsi_key &key)
{
bool result = true;
try { boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key); }
catch (...) { result = false; }
return result;
}
static bool Remove(const boost::interprocess::xsi_key &key)
{
bool ret = false;
try
{
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
boost::interprocess::xsi_shared_memory xsi(boost::interprocess::open_only, key);
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
}
catch (const boost::interprocess::interprocess_exception &e)
{
if (e.get_error_code() != boost::interprocess::not_found_error)
{
throw;
}
}
return ret;
}
boost::interprocess::xsi_key key;
boost::interprocess::xsi_shared_memory shm;
boost::interprocess::mapped_region region;
shm_remove remover;
};
#else
// Windows - specific code
class SharedMemory
{
SharedMemory(const SharedMemory&) = delete;
// Remove shared memory on destruction
class shm_remove
{
private:
shm_remove(const shm_remove&) = delete;
char *m_shmid;
bool m_initialized;
public:
void SetID(char *shmid)
{
m_shmid = shmid;
m_initialized = true;
}
shm_remove() : m_shmid("undefined"), m_initialized(false) {}
~shm_remove()
{
if (m_initialized)
{
SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
if (!boost::interprocess::shared_memory_object::remove(m_shmid))
{
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
}
}
}
};
public:
void *Ptr() const { return region.get_address(); }
SharedMemory(const boost::filesystem::path &lock_file,
const int id,
const uint64_t size = 0,
bool read_write = false,
bool remove_prev = true)
{
sprintf(key, "%s.%d", "osrm.lock", id);
if (0 == size)
{ // read_only
shm = boost::interprocess::shared_memory_object(
boost::interprocess::open_only,
key,
read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
region = boost::interprocess::mapped_region(
shm, read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
}
else
{ // writeable pointer
// remove previously allocated mem
if (remove_prev)
{
Remove(key);
}
shm = boost::interprocess::shared_memory_object(
boost::interprocess::open_or_create, key, boost::interprocess::read_write);
shm.truncate(size);
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
remover.SetID(key);
SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
}
}
static bool RegionExists(const int id)
{
bool result = true;
try
{
char k[500];
build_key(id, k);
result = RegionExists(k);
}
catch (...) { result = false; }
return result;
}
static bool Remove(const int id)
{
char k[500];
build_key(id, k);
return Remove(k);
}
private:
static void build_key(int id, char *key)
{
sprintf(key, "%s.%d", "osrm.lock", id);
}
static bool RegionExists(const char *key)
{
bool result = true;
try
{
boost::interprocess::shared_memory_object shm(
boost::interprocess::open_only, key, boost::interprocess::read_write);
}
catch (...) { result = false; }
return result;
}
static bool Remove(char *key)
{
bool ret = false;
try
{
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
ret = boost::interprocess::shared_memory_object::remove(key);
}
catch (const boost::interprocess::interprocess_exception &e)
{
if (e.get_error_code() != boost::interprocess::not_found_error)
{
throw;
}
}
return ret;
}
char key[500];
boost::interprocess::shared_memory_object shm;
boost::interprocess::mapped_region region;
shm_remove remover;
};
#endif
template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
{
public:
template <typename IdentifierT>
static SharedMemory *Get(const IdentifierT &id,
const uint64_t size = 0,
bool read_write = false,
bool remove_prev = true)
{
try
{
LockFileT lock_file;
if (!boost::filesystem::exists(lock_file()))
{
if (0 == size)
{
throw OSRMException("lock file does not exist, exiting");
}
else
{
boost::filesystem::ofstream ofs(lock_file());
ofs.close();
}
}
return new SharedMemory(lock_file(), id, size, read_write, remove_prev);
}
catch (const boost::interprocess::interprocess_exception &e)
{
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code "
<< e.get_error_code();
throw OSRMException(e.what());
}
}
SharedMemoryFactory_tmpl() = delete;
SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
};
using SharedMemoryFactory = SharedMemoryFactory_tmpl<>;
#endif // SHARED_MEMORY_FACTORY_HPP
@@ -0,0 +1,154 @@
/*
Copyright (c) 2014, 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 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
+204
View File
@@ -0,0 +1,204 @@
/*
Copyright (c) 2014, 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 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 <tbb/parallel_sort.h>
#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));
}
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
{
tbb::parallel_sort(graph.begin(), graph.end());
number_of_nodes = nodes;
number_of_edges = (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 (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
{
edge_array[i].target = graph[edge].target;
edge_array[i].data = graph[edge].data;
BOOST_ASSERT(edge_array[i].data.distance > 0);
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);
}
inline 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
{
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
+260
View File
@@ -0,0 +1,260 @@
/*
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.
*/
// KD Tree coded by Christian Vetter, Monav Project
#ifndef STATICKDTREE_HPP
#define STATICKDTREE_HPP
#include <boost/assert.hpp>
#include <vector>
#include <algorithm>
#include <stack>
#include <limits>
namespace KDTree
{
#define KDTREE_BASESIZE (8)
template <unsigned k, typename T> class BoundingBox
{
public:
BoundingBox()
{
for (unsigned dim = 0; dim < k; ++dim)
{
min[dim] = std::numeric_limits<T>::min();
max[dim] = std::numeric_limits<T>::max();
}
}
T min[k];
T max[k];
};
struct NoData
{
};
template <unsigned k, typename T> class EuclidianMetric
{
public:
double operator()(const T left[k], const T right[k])
{
double result = 0;
for (unsigned i = 0; i < k; ++i)
{
double temp = (double)left[i] - (double)right[i];
result += temp * temp;
}
return result;
}
double operator()(const BoundingBox<k, T> &box, const T point[k])
{
T nearest[k];
for (unsigned dim = 0; dim < k; ++dim)
{
if (point[dim] < box.min[dim])
nearest[dim] = box.min[dim];
else if (point[dim] > box.max[dim])
nearest[dim] = box.max[dim];
else
nearest[dim] = point[dim];
}
return operator()(point, nearest);
}
};
template <unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric<k, T>>
class StaticKDTree
{
public:
struct InputPoint
{
T coordinates[k];
Data data;
bool operator==(const InputPoint &right)
{
for (int i = 0; i < k; i++)
{
if (coordinates[i] != right.coordinates[i])
return false;
}
return true;
}
};
explicit StaticKDTree(std::vector<InputPoint> *points)
{
BOOST_ASSERT(k > 0);
BOOST_ASSERT(points->size() > 0);
size = points->size();
kdtree = new InputPoint[size];
for (Iterator i = 0; i != size; ++i)
{
kdtree[i] = points->at(i);
for (unsigned dim = 0; dim < k; ++dim)
{
if (kdtree[i].coordinates[dim] < boundingBox.min[dim])
boundingBox.min[dim] = kdtree[i].coordinates[dim];
if (kdtree[i].coordinates[dim] > boundingBox.max[dim])
boundingBox.max[dim] = kdtree[i].coordinates[dim];
}
}
std::stack<Tree> s;
s.push(Tree(0, size, 0));
while (!s.empty())
{
Tree tree = s.top();
s.pop();
if (tree.right - tree.left < KDTREE_BASESIZE)
continue;
Iterator middle = tree.left + (tree.right - tree.left) / 2;
std::nth_element(
kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less(tree.dimension));
s.push(Tree(tree.left, middle, (tree.dimension + 1) % k));
s.push(Tree(middle + 1, tree.right, (tree.dimension + 1) % k));
}
}
~StaticKDTree() { delete[] kdtree; }
bool NearestNeighbor(InputPoint *result, const InputPoint &point)
{
Metric distance;
bool found = false;
double nearestDistance = std::numeric_limits<T>::max();
std::stack<NNTree> s;
s.push(NNTree(0, size, 0, boundingBox));
while (!s.empty())
{
NNTree tree = s.top();
s.pop();
if (distance(tree.box, point.coordinates) >= nearestDistance)
continue;
if (tree.right - tree.left < KDTREE_BASESIZE)
{
for (unsigned i = tree.left; i < tree.right; i++)
{
double newDistance = distance(kdtree[i].coordinates, point.coordinates);
if (newDistance < nearestDistance)
{
nearestDistance = newDistance;
*result = kdtree[i];
found = true;
}
}
continue;
}
Iterator middle = tree.left + (tree.right - tree.left) / 2;
double newDistance = distance(kdtree[middle].coordinates, point.coordinates);
if (newDistance < nearestDistance)
{
nearestDistance = newDistance;
*result = kdtree[middle];
found = true;
}
Less comperator(tree.dimension);
if (!comperator(point, kdtree[middle]))
{
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
s.push(second);
s.push(first);
}
else
{
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
s.push(first);
s.push(second);
}
}
return found;
}
private:
using Iterator = unsigned;
struct Tree
{
Iterator left;
Iterator right;
unsigned dimension;
Tree() {}
Tree(Iterator l, Iterator r, unsigned d) : left(l), right(r), dimension(d) {}
};
struct NNTree
{
Iterator left;
Iterator right;
unsigned dimension;
BoundingBox<k, T> box;
NNTree() {}
NNTree(Iterator l, Iterator r, unsigned d, const BoundingBox<k, T> &b)
: left(l), right(r), dimension(d), box(b)
{
}
};
class Less
{
public:
explicit Less(unsigned d)
{
dimension = d;
BOOST_ASSERT(dimension < k);
}
bool operator()(const InputPoint &left, const InputPoint &right)
{
BOOST_ASSERT(dimension < k);
return left.coordinates[dimension] < right.coordinates[dimension];
}
private:
unsigned dimension;
};
BoundingBox<k, T> boundingBox;
InputPoint *kdtree;
Iterator size;
};
}
#endif // STATICKDTREE_HPP
File diff suppressed because it is too large Load Diff
+36
View File
@@ -0,0 +1,36 @@
/*
Copyright (c) 2014, 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 TRAVEL_MODE_HPP
#define TRAVEL_MODE_HPP
namespace {
using TravelMode = unsigned char;
static const TravelMode TRAVEL_MODE_INACCESSIBLE = 0;
static const TravelMode TRAVEL_MODE_DEFAULT = 1;
}
#endif /* TRAVEL_MODE_HPP */
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright (c) 2014, 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 TURN_INSTRUCTIONS_HPP
#define TURN_INSTRUCTIONS_HPP
enum class TurnInstruction : unsigned char
{
NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn,
TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaLocation, HeadOn, EnterRoundAbout,
LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination,
EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection,
InverseAccessRestrictionFlag = 127,
AccessRestrictionFlag = 128,
AccessRestrictionPenalty = 129
};
struct TurnInstructionsClass
{
TurnInstructionsClass() = delete;
TurnInstructionsClass(const TurnInstructionsClass&) = delete;
static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle)
{
if (angle >= 23 && angle < 67)
{
return TurnInstruction::TurnSharpRight;
}
if (angle >= 67 && angle < 113)
{
return TurnInstruction::TurnRight;
}
if (angle >= 113 && angle < 158)
{
return TurnInstruction::TurnSlightRight;
}
if (angle >= 158 && angle < 202)
{
return TurnInstruction::GoStraight;
}
if (angle >= 202 && angle < 248)
{
return TurnInstruction::TurnSlightLeft;
}
if (angle >= 248 && angle < 292)
{
return TurnInstruction::TurnLeft;
}
if (angle >= 292 && angle < 336)
{
return TurnInstruction::TurnSharpLeft;
}
return TurnInstruction::UTurn;
}
static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
{
if (TurnInstruction::NoTurn == turn_instruction || TurnInstruction::StayOnRoundAbout == turn_instruction)
{
return false;
}
return true;
}
};
#endif /* TURN_INSTRUCTIONS_HPP */
+115
View File
@@ -0,0 +1,115 @@
/*
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 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] = i;
table2[i] = 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] = i;
table2[i] = i;
table3[i] = i;
table4[i] = 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
+89
View File
@@ -0,0 +1,89 @@
/*
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 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
{
Key key;
NodeID id;
unsigned time;
HashCell()
: key(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
time(std::numeric_limits<unsigned>::max())
{
}
HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
operator Key() const { return key; }
void operator=(const Key &key_to_insert) { key = key_to_insert; }
};
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].id = node;
positions[position].time = current_timestamp;
return positions[position];
}
void Clear()
{
++current_timestamp;
if (std::numeric_limits<unsigned>::max() == current_timestamp)
{
positions.clear();
positions.resize((2 << 16));
}
}
private:
XORFastHashStorage() : positions(2 << 16), current_timestamp(0) {}
std::vector<HashCell> positions;
XORFastHash fast_hasher;
unsigned current_timestamp;
};
#endif // XOR_FAST_HASH_STORAGE_HPP