Compare commits
171 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a1ecab2f95 | |||
| b7704f0c7f | |||
| d6962f3a09 | |||
| e44ebe0743 | |||
| f02ec41fbc | |||
| d0b4ffd154 | |||
| 265af1f790 | |||
| 241d6b482e | |||
| 45f0af2afc | |||
| 7955066d5c | |||
| ec3f9695cd | |||
| 018c144c76 | |||
| 56e88b2a56 | |||
| a2bdc5d8d9 | |||
| 1b257f7547 | |||
| 5d6b05979d | |||
| 538f8d040a | |||
| 7d52aa1272 | |||
| d316202834 | |||
| 0167dfc3c9 | |||
| 02dc3dee04 | |||
| a5d3bc9578 | |||
| cfbc6b0441 | |||
| 8c5f8e995e | |||
| b77dd6699d | |||
| 9a153708e6 | |||
| e0027a78e1 | |||
| 51e8113a69 | |||
| 78f5753a3a | |||
| 16ca8da438 | |||
| ca6515c58a | |||
| 2ec952032a | |||
| b0b67a0cdc | |||
| 0eed39cdf1 | |||
| ace59411cb | |||
| ef7619d664 | |||
| 0f8a32f38c | |||
| c6a58ff1b4 | |||
| 45f751720a | |||
| ca016e2818 | |||
| 5da01946b8 | |||
| 8b3002a685 | |||
| ede5cca2e7 | |||
| d0e158ca07 | |||
| 09dc21af31 | |||
| 2435fadfbd | |||
| edef9c11f7 | |||
| 2c9edcaf23 | |||
| 18861d58b5 | |||
| 9b3dab8055 | |||
| 7a6a5f6612 | |||
| f468fcc2b6 | |||
| 5d93c68790 | |||
| fa04706484 | |||
| d09be5a80e | |||
| a4d6e5c9cc | |||
| 4f85fd28cf | |||
| 39914cd933 | |||
| 038e8cc8b8 | |||
| db5fd5506d | |||
| f2be495e95 | |||
| 6d8465a04d | |||
| 4bb5270f25 | |||
| 0f06c71796 | |||
| 5b8d8a83dd | |||
| 8ec3d549a6 | |||
| 394e369b54 | |||
| 899ab9ddc0 | |||
| 8ae467985f | |||
| 9ccc8a7404 | |||
| 0b89a9d554 | |||
| 752fb880be | |||
| 549bcb502b | |||
| 44077cb007 | |||
| 7b5902a580 | |||
| 2861bacd2a | |||
| 776ac3bb2a | |||
| b429d9f509 | |||
| 26397e4692 | |||
| 48d23194af | |||
| bcaea1a617 | |||
| 12b43d206c | |||
| 9cc49f6ff3 | |||
| 87f036e538 | |||
| fdebec6448 | |||
| ba37836e24 | |||
| b60cfd9294 | |||
| bc0665cd9f | |||
| 0dbe5e6593 | |||
| 9b33aaa11a | |||
| 024b78da7c | |||
| 2a64297506 | |||
| 09c76939f1 | |||
| 0b3f3bdf92 | |||
| 3b29eeb6b6 | |||
| 985270bb02 | |||
| 6b91d6692f | |||
| eca09e6c81 | |||
| 874c579f86 | |||
| a0bddab169 | |||
| b679a94930 | |||
| 5bde545ce3 | |||
| e68c750389 | |||
| f16cb3c52d | |||
| f7d5b0db9c | |||
| ba0b664e3f | |||
| 149d037824 | |||
| d0349d9b0d | |||
| c71c8b0047 | |||
| 3be644265b | |||
| cd6874ca60 | |||
| 7083978f9d | |||
| 4d132489c1 | |||
| b5170ed1fd | |||
| cc915dbef2 | |||
| 9a5bf1ee95 | |||
| a14b6af5c0 | |||
| ec372ad01d | |||
| 8a412ef69e | |||
| c978364f49 | |||
| 61d2a99dd4 | |||
| fdba916d83 | |||
| a12209e61d | |||
| fc6607ce9e | |||
| 62ccbc7490 | |||
| b2b36984e1 | |||
| c10208407d | |||
| 64720c2d2e | |||
| da81e4839a | |||
| 25013afdd2 | |||
| 678829ab28 | |||
| d8dffa9d71 | |||
| be8810077a | |||
| ee4ecb9783 | |||
| eaed8572f0 | |||
| e91e6fb068 | |||
| cb17a0a49b | |||
| 248df9ca2d | |||
| fa615ed9f4 | |||
| 65aa4af6d9 | |||
| df56ad476e | |||
| 8e20fa89e8 | |||
| 76058729e0 | |||
| 88a0cc8c9c | |||
| 2ea45c0c58 | |||
| bf27f41f52 | |||
| 853f6012d5 | |||
| 14ad02777f | |||
| c1eb00f6d5 | |||
| e5adaf974d | |||
| 727a29600d | |||
| a5ebdb9243 | |||
| 2ef37ee798 | |||
| c23575786c | |||
| 5a0d693c93 | |||
| c6902528b3 | |||
| f90993be86 | |||
| e7db076648 | |||
| 6d52a7d3d4 | |||
| 3368b492b9 | |||
| 1222aa6d25 | |||
| 67efd150d4 | |||
| 9894f2e053 | |||
| 3a1a51ac46 | |||
| a1b5429f4e | |||
| b11e39554f | |||
| a92c764945 | |||
| f581396f1d | |||
| 6814926f05 | |||
| b8f882dba4 | |||
| 783e8edf71 |
@@ -0,0 +1,54 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
AlignEscapedNewlinesLeft: false
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: true
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BinPackParameters: false
|
||||
ColumnLimit: 100
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
DerivePointerBinding: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
IndentCaseLabels: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
NamespaceIndentation: None
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyExcessCharacter: 1000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerBindsToType: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
Cpp11BracedListStyle: true
|
||||
Standard: Cpp11
|
||||
IndentWidth: 4
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
BreakBeforeBraces: Allman
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInAngles: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
ContinuationIndentWidth: 4
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
SpaceBeforeParens: ControlStatements
|
||||
...
|
||||
|
||||
@@ -96,7 +96,7 @@ private:
|
||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||
typedef std::pair<NodeID, bool> restriction_target;
|
||||
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
||||
typedef boost::unordered_map<RestrictionSource, unsigned> RestrictionMap;
|
||||
|
||||
std::vector<NodeInfo> m_coordinate_list;
|
||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||
@@ -145,7 +145,7 @@ public:
|
||||
if(restriction_iterator == m_restriction_map.end()) {
|
||||
index = m_restriction_bucket_list.size();
|
||||
m_restriction_bucket_list.resize(index+1);
|
||||
m_restriction_map[restrictionSource] = index;
|
||||
m_restriction_map.insert(std::make_pair(restrictionSource, index));
|
||||
} else {
|
||||
index = restriction_iterator->second;
|
||||
//Map already contains an is_only_*-restriction
|
||||
@@ -358,6 +358,7 @@ public:
|
||||
"identified: " << component_size_vector.size() <<
|
||||
" many components, marking small components";
|
||||
|
||||
// TODO/C++11: prime candidate for lambda function
|
||||
unsigned size_one_counter = 0;
|
||||
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
|
||||
if(1 == component_size_vector[i]) {
|
||||
|
||||
+2
-2
@@ -81,7 +81,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
message(STATUS "Configuring OSRM in debug mode")
|
||||
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
message(STATUS "adding profiling flags")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
endif()
|
||||
endif()
|
||||
@@ -92,7 +92,7 @@ endif()
|
||||
# Configuring compilers
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
# using Clang
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
|
||||
message(STATUS "OpenMP parallelization not available using clang++")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
# using GCC
|
||||
|
||||
@@ -126,7 +126,6 @@ public:
|
||||
newEdge.source = diter->source();
|
||||
newEdge.target = diter->target();
|
||||
newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
|
||||
|
||||
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
|
||||
#ifndef NDEBUG
|
||||
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
||||
@@ -737,6 +736,7 @@ private:
|
||||
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||
return false;
|
||||
}
|
||||
// TODO: C++11 copy_if with lambda
|
||||
neighbours.push_back( target );
|
||||
}
|
||||
|
||||
|
||||
@@ -33,13 +33,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
//TODO: CompressionWorker
|
||||
//TODO: EdgeBasedEdgeGenerator
|
||||
|
||||
// template<class Work>
|
||||
// inline static void TraverseGraph(NodeBasedDynamicGraph & graph, Work & work) {
|
||||
|
||||
// }
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <numeric>
|
||||
|
||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
int number_of_nodes,
|
||||
@@ -48,12 +44,14 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
std::vector<NodeID> & traffic_light_node_list,
|
||||
std::vector<TurnRestriction> & input_restrictions_list,
|
||||
std::vector<NodeInfo> & m_node_info_list,
|
||||
SpeedProfileProperties speed_profile
|
||||
SpeedProfileProperties & speed_profile
|
||||
) : speed_profile(speed_profile),
|
||||
m_turn_restrictions_count(0),
|
||||
m_node_info_list(m_node_info_list)
|
||||
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
|
||||
m_node_info_list(m_node_info_list),
|
||||
max_id(0)
|
||||
{
|
||||
BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) {
|
||||
BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) {
|
||||
std::pair<NodeID, NodeID> restriction_source =
|
||||
std::make_pair(restriction.fromNode, restriction.viaNode);
|
||||
unsigned index;
|
||||
@@ -80,7 +78,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
);
|
||||
}
|
||||
|
||||
m_barrier_nodes.insert(
|
||||
m_barrier_nodes.insert(
|
||||
barrier_node_list.begin(),
|
||||
barrier_node_list.end()
|
||||
);
|
||||
@@ -90,10 +88,15 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
traffic_light_node_list.end()
|
||||
);
|
||||
|
||||
DeallocatingVector< NodeBasedEdge > edges_list;
|
||||
std::sort( input_edge_list.begin(), input_edge_list.end() );
|
||||
|
||||
//TODO: remove duplicate edges
|
||||
|
||||
DeallocatingVector<NodeBasedEdge> edges_list;
|
||||
NodeBasedEdge edge;
|
||||
BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) {
|
||||
if(!import_edge.isForward()) {
|
||||
|
||||
if( !import_edge.isForward() ) {
|
||||
edge.source = import_edge.target();
|
||||
edge.target = import_edge.source();
|
||||
edge.data.backward = import_edge.isForward();
|
||||
@@ -104,33 +107,101 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
edge.data.forward = import_edge.isForward();
|
||||
edge.data.backward = import_edge.isBackward();
|
||||
}
|
||||
if(edge.source == edge.target) {
|
||||
continue;
|
||||
|
||||
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.isRoundabout();
|
||||
edge.data.ignoreInGrid = import_edge.ignoreInGrid();
|
||||
edge.data.ignore_in_grid = import_edge.ignoreInGrid();
|
||||
edge.data.nameID = import_edge.name();
|
||||
edge.data.type = import_edge.type();
|
||||
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
|
||||
edge.data.edgeBasedNodeID = edges_list.size();
|
||||
edge.data.contraFlow = import_edge.isContraFlow();
|
||||
edges_list.push_back( edge );
|
||||
if( edge.data.backward ) {
|
||||
std::swap( edge.source, edge.target );
|
||||
edge.data.forward = import_edge.isBackward();
|
||||
edge.data.backward = import_edge.isForward();
|
||||
edge.data.edgeBasedNodeID = edges_list.size();
|
||||
|
||||
if( !import_edge.IsSplit() ) {
|
||||
using std::swap; //enable ADL
|
||||
swap( edge.source, edge.target );
|
||||
edge.data.SwapDirectionFlags();
|
||||
edges_list.push_back( edge );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ImportEdge>().swap(input_edge_list);
|
||||
std::sort( edges_list.begin(), edges_list.end() );
|
||||
|
||||
m_node_based_graph = boost::make_shared<NodeBasedDynamicGraph>(
|
||||
number_of_nodes, edges_list
|
||||
number_of_nodes,
|
||||
edges_list
|
||||
);
|
||||
DeallocatingVector<NodeBasedEdge>().swap(edges_list);
|
||||
BOOST_ASSERT(0 == edges_list.size() );
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::FixupArrivingTurnRestriction(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
) {
|
||||
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
|
||||
BOOST_ASSERT( v != std::numeric_limits<unsigned>::max() );
|
||||
BOOST_ASSERT( w != std::numeric_limits<unsigned>::max() );
|
||||
|
||||
std::vector<NodeID> predecessors;
|
||||
for(
|
||||
EdgeID current_edge_id = m_node_based_graph->BeginEdges(u);
|
||||
current_edge_id < m_node_based_graph->EndEdges(u);
|
||||
++current_edge_id
|
||||
) {
|
||||
const EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge_id);
|
||||
const NodeID target = m_node_based_graph->GetTarget(current_edge_id);
|
||||
if( edge_data.backward && ( v != target) ) {
|
||||
predecessors.push_back(target);
|
||||
}
|
||||
}
|
||||
BOOST_FOREACH( const NodeID x, predecessors ) {
|
||||
const std::pair<NodeID, NodeID> restr_start = std::make_pair(x,u);
|
||||
RestrictionMap::const_iterator restriction_iterator;
|
||||
restriction_iterator = m_restriction_map.find( restr_start );
|
||||
if( restriction_iterator != m_restriction_map.end() ) {
|
||||
const unsigned index = restriction_iterator->second;
|
||||
BOOST_FOREACH(
|
||||
RestrictionTarget & restriction_target,
|
||||
m_restriction_bucket_list.at(index)
|
||||
) {
|
||||
if( v == restriction_target.first ) {
|
||||
restriction_target.first = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::FixupStartingTurnRestriction(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
) {
|
||||
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
|
||||
BOOST_ASSERT( v != std::numeric_limits<unsigned>::max() );
|
||||
BOOST_ASSERT( w != std::numeric_limits<unsigned>::max() );
|
||||
|
||||
const std::pair<NodeID, NodeID> old_start = std::make_pair(v,w);
|
||||
RestrictionMap::const_iterator restriction_iterator;
|
||||
restriction_iterator = m_restriction_map.find( old_start );
|
||||
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 );
|
||||
|
||||
// insert new restriction start (u,w) (point to index)
|
||||
const std::pair<NodeID, NodeID> new_start = std::make_pair(u,w);
|
||||
m_restriction_map.insert( std::make_pair(new_start, index) );
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedEdges(
|
||||
@@ -146,8 +217,11 @@ void EdgeBasedGraphFactory::GetEdgeBasedEdges(
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
|
||||
#ifndef NDEBUG
|
||||
BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){
|
||||
BOOST_ASSERT(node.lat1 != INT_MAX); BOOST_ASSERT(node.lon1 != INT_MAX);
|
||||
BOOST_ASSERT(node.lat2 != INT_MAX); BOOST_ASSERT(node.lon2 != INT_MAX);
|
||||
|
||||
BOOST_ASSERT( m_node_info_list.at(node.u).lat != INT_MAX );
|
||||
BOOST_ASSERT( m_node_info_list.at(node.u).lon != INT_MAX );
|
||||
BOOST_ASSERT( m_node_info_list.at(node.v).lon != INT_MAX );
|
||||
BOOST_ASSERT( m_node_info_list.at(node.v).lat != INT_MAX );
|
||||
}
|
||||
#endif
|
||||
nodes.swap(m_edge_based_node_list);
|
||||
@@ -157,7 +231,9 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
|
||||
const NodeID u,
|
||||
const NodeID v
|
||||
) const {
|
||||
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
|
||||
BOOST_ASSERT( v != std::numeric_limits<unsigned>::max() );
|
||||
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
|
||||
RestrictionMap::const_iterator restriction_iter;
|
||||
restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if (restriction_iter != m_restriction_map.end()) {
|
||||
@@ -171,7 +247,7 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
|
||||
}
|
||||
}
|
||||
}
|
||||
return UINT_MAX;
|
||||
return std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
|
||||
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
||||
@@ -179,8 +255,11 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
) const {
|
||||
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
||||
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
|
||||
BOOST_ASSERT( v != std::numeric_limits<unsigned>::max() );
|
||||
BOOST_ASSERT( w != std::numeric_limits<unsigned>::max() );
|
||||
|
||||
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
|
||||
RestrictionMap::const_iterator restriction_iter;
|
||||
restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if (restriction_iter != m_restriction_map.end()) {
|
||||
@@ -189,7 +268,10 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
||||
const RestrictionTarget & restriction_target,
|
||||
m_restriction_bucket_list.at(index)
|
||||
) {
|
||||
if(w == restriction_target.first) {
|
||||
if(
|
||||
( w == restriction_target.first ) && // target found
|
||||
( !restriction_target.second ) // and not an only_-restr.
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -198,22 +280,175 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
|
||||
EdgeIterator e1,
|
||||
NodeIterator u,
|
||||
NodeIterator v,
|
||||
bool belongsToTinyComponent) {
|
||||
EdgeData & data = m_node_based_graph->GetEdgeData(e1);
|
||||
EdgeBasedNode currentNode;
|
||||
currentNode.nameID = data.nameID;
|
||||
currentNode.lat1 = m_node_info_list[u].lat;
|
||||
currentNode.lon1 = m_node_info_list[u].lon;
|
||||
currentNode.lat2 = m_node_info_list[v].lat;
|
||||
currentNode.lon2 = m_node_info_list[v].lon;
|
||||
currentNode.belongsToTinyComponent = belongsToTinyComponent;
|
||||
currentNode.id = data.edgeBasedNodeID;
|
||||
currentNode.ignoreInGrid = data.ignoreInGrid;
|
||||
currentNode.weight = data.distance;
|
||||
m_edge_based_node_list.push_back(currentNode);
|
||||
NodeIterator u,
|
||||
NodeIterator v,
|
||||
EdgeIterator e1,
|
||||
bool belongs_to_tiny_cc
|
||||
) {
|
||||
// merge edges together into one EdgeBasedNode
|
||||
BOOST_ASSERT( u != SPECIAL_NODEID );
|
||||
BOOST_ASSERT( v != SPECIAL_NODEID );
|
||||
BOOST_ASSERT( e1 != SPECIAL_EDGEID );
|
||||
|
||||
#ifndef NDEBUG
|
||||
// find forward edge id and
|
||||
const EdgeID e1b = m_node_based_graph->FindEdge(u, v);
|
||||
BOOST_ASSERT( e1 == e1b );
|
||||
#endif
|
||||
|
||||
BOOST_ASSERT( e1 != SPECIAL_EDGEID );
|
||||
const EdgeData & forward_data = m_node_based_graph->GetEdgeData(e1);
|
||||
|
||||
// find reverse edge id and
|
||||
const EdgeID e2 = m_node_based_graph->FindEdge(v, u);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ( e2 == m_node_based_graph->EndEdges(v) ) {
|
||||
SimpleLogger().Write(logWARNING) << "Did not find edge (" << v << "," << u << ")";
|
||||
}
|
||||
#endif
|
||||
BOOST_ASSERT( e2 != SPECIAL_EDGEID );
|
||||
BOOST_ASSERT( e2 < m_node_based_graph->EndEdges(v) );
|
||||
const EdgeData & reverse_data = m_node_based_graph->GetEdgeData(e2);
|
||||
|
||||
if(
|
||||
forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
|
||||
reverse_data.edgeBasedNodeID == SPECIAL_NODEID
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_ASSERT( m_geometry_compressor.HasEntryForID(e1) == m_geometry_compressor.HasEntryForID(e2) );
|
||||
if( m_geometry_compressor.HasEntryForID(e1) ) {
|
||||
|
||||
BOOST_ASSERT( m_geometry_compressor.HasEntryForID(e2) );
|
||||
|
||||
// reconstruct geometry and put in each individual edge with its offset
|
||||
const std::vector<GeometryCompressor::CompressedNode> & forward_geometry = m_geometry_compressor.GetBucketReference(e1);
|
||||
const std::vector<GeometryCompressor::CompressedNode> & reverse_geometry = m_geometry_compressor.GetBucketReference(e2);
|
||||
BOOST_ASSERT( forward_geometry.size() == reverse_geometry.size() );
|
||||
BOOST_ASSERT( 0 != forward_geometry.size() );
|
||||
|
||||
// reconstruct bidirectional edge with individual weights and put each into the NN index
|
||||
|
||||
std::vector<int> forward_dist_prefix_sum(forward_geometry.size(), 0);
|
||||
std::vector<int> reverse_dist_prefix_sum(reverse_geometry.size(), 0);
|
||||
|
||||
// quick'n'dirty prefix sum as std::partial_sum needs addtional casts
|
||||
// TODO: move to lambda function with C++11
|
||||
int temp_sum = 0;
|
||||
|
||||
for (unsigned i = 0; i < forward_geometry.size(); ++i)
|
||||
{
|
||||
forward_dist_prefix_sum[i] = temp_sum;
|
||||
temp_sum += forward_geometry[i].second;
|
||||
|
||||
BOOST_ASSERT( forward_data.distance >= temp_sum );
|
||||
}
|
||||
|
||||
temp_sum = 0;
|
||||
for( unsigned i = 0; i < reverse_geometry.size(); ++i ) {
|
||||
temp_sum += reverse_geometry[reverse_geometry.size()-1-i].second;
|
||||
reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
|
||||
BOOST_ASSERT( reverse_data.distance >= temp_sum );
|
||||
}
|
||||
|
||||
BOOST_ASSERT( forward_geometry.size() == reverse_geometry.size() );
|
||||
|
||||
const unsigned geometry_size = forward_geometry.size();
|
||||
BOOST_ASSERT( geometry_size > 1 );
|
||||
NodeID current_edge_start_coordinate_id = u;
|
||||
|
||||
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
|
||||
{
|
||||
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
|
||||
}
|
||||
if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID)
|
||||
{
|
||||
max_id = std::max(reverse_data.edgeBasedNodeID, max_id);
|
||||
}
|
||||
|
||||
// traverse arrays from start and end respectively
|
||||
for( unsigned i = 0; i < geometry_size; ++i ) {
|
||||
BOOST_ASSERT( current_edge_start_coordinate_id == reverse_geometry[geometry_size-1-i].first );
|
||||
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
|
||||
BOOST_ASSERT( current_edge_target_coordinate_id != current_edge_start_coordinate_id);
|
||||
|
||||
// build edges
|
||||
m_edge_based_node_list.push_back(
|
||||
EdgeBasedNode(
|
||||
forward_data.edgeBasedNodeID,
|
||||
reverse_data.edgeBasedNodeID,
|
||||
current_edge_start_coordinate_id,
|
||||
current_edge_target_coordinate_id,
|
||||
forward_data.nameID,
|
||||
forward_geometry[i].second,
|
||||
reverse_geometry[i].second,
|
||||
forward_dist_prefix_sum[i],
|
||||
reverse_dist_prefix_sum[i],
|
||||
m_geometry_compressor.GetPositionForID(e1),
|
||||
i,
|
||||
belongs_to_tiny_cc
|
||||
)
|
||||
);
|
||||
current_edge_start_coordinate_id = current_edge_target_coordinate_id;
|
||||
|
||||
BOOST_ASSERT( m_edge_based_node_list.back().IsCompressed() );
|
||||
|
||||
BOOST_ASSERT(
|
||||
u != m_edge_based_node_list.back().u ||
|
||||
v != m_edge_based_node_list.back().v
|
||||
);
|
||||
|
||||
BOOST_ASSERT(
|
||||
u != m_edge_based_node_list.back().v ||
|
||||
v != m_edge_based_node_list.back().u
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_ASSERT( current_edge_start_coordinate_id == v );
|
||||
BOOST_ASSERT( m_edge_based_node_list.back().IsCompressed() );
|
||||
|
||||
} else {
|
||||
BOOST_ASSERT( !m_geometry_compressor.HasEntryForID(e2) );
|
||||
|
||||
if( forward_data.edgeBasedNodeID != std::numeric_limits<unsigned>::max() ) {
|
||||
BOOST_ASSERT( forward_data.forward );
|
||||
}
|
||||
if( reverse_data.edgeBasedNodeID != std::numeric_limits<unsigned>::max() ) {
|
||||
BOOST_ASSERT( reverse_data.forward );
|
||||
}
|
||||
if( forward_data.edgeBasedNodeID == std::numeric_limits<unsigned>::max() ) {
|
||||
BOOST_ASSERT( !forward_data.forward );
|
||||
}
|
||||
if( reverse_data.edgeBasedNodeID == std::numeric_limits<unsigned>::max() ) {
|
||||
BOOST_ASSERT( !reverse_data.forward );
|
||||
}
|
||||
|
||||
BOOST_ASSERT(
|
||||
forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
|
||||
reverse_data.edgeBasedNodeID != SPECIAL_NODEID
|
||||
);
|
||||
|
||||
//TODO C++11: emplace_back with
|
||||
m_edge_based_node_list.push_back(
|
||||
EdgeBasedNode(
|
||||
forward_data.edgeBasedNodeID,
|
||||
reverse_data.edgeBasedNodeID,
|
||||
u,
|
||||
v,
|
||||
forward_data.nameID,
|
||||
forward_data.distance,
|
||||
reverse_data.distance,
|
||||
0,
|
||||
0,
|
||||
SPECIAL_EDGEID,
|
||||
0,
|
||||
belongs_to_tiny_cc
|
||||
)
|
||||
);
|
||||
BOOST_ASSERT( !m_edge_based_node_list.back().IsCompressed() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -229,27 +464,173 @@ void EdgeBasedGraphFactory::FlushVectorToStream(
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::Run(
|
||||
const char * original_edge_data_filename,
|
||||
const std::string & original_edge_data_filename,
|
||||
const std::string & geometry_filename,
|
||||
lua_State *lua_state
|
||||
) {
|
||||
SimpleLogger().Write() << "Compressing geometry of input graph";
|
||||
//TODO: iterate over all turns
|
||||
SimpleLogger().Write() << "Removing graph geometry while preserving topology";
|
||||
|
||||
//TODO: compress geometries
|
||||
const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
|
||||
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
|
||||
|
||||
//TODO: update turn restrictions if concerned by compression
|
||||
Percent p(original_number_of_nodes);
|
||||
unsigned removed_node_count = 0;
|
||||
|
||||
//TODO: do some compression statistics
|
||||
for( NodeID v = 0; v < original_number_of_nodes; ++v ) {
|
||||
p.printStatus(v);
|
||||
|
||||
// only contract degree 2 vertices
|
||||
if( 2 != m_node_based_graph->GetOutDegree(v) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't contract barrier node
|
||||
if( m_barrier_nodes.end() != m_barrier_nodes.find(v) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool reverse_edge_order = !(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(v)).forward);
|
||||
const EdgeIterator forward_e2 = m_node_based_graph->BeginEdges(v) + reverse_edge_order;
|
||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != forward_e2 );
|
||||
const EdgeIterator reverse_e2 = m_node_based_graph->BeginEdges(v) + 1 - reverse_edge_order;
|
||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != reverse_e2 );
|
||||
|
||||
const EdgeData & fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
|
||||
const EdgeData & rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
|
||||
|
||||
const NodeIterator w = m_node_based_graph->GetTarget(forward_e2);
|
||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != w );
|
||||
BOOST_ASSERT( v != w );
|
||||
const NodeIterator u = m_node_based_graph->GetTarget(reverse_e2);
|
||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != u );
|
||||
BOOST_ASSERT( u != v );
|
||||
|
||||
const EdgeIterator forward_e1 = m_node_based_graph->FindEdge(u, v);
|
||||
BOOST_ASSERT( m_node_based_graph->EndEdges(u) != forward_e1 );
|
||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != forward_e1 );
|
||||
BOOST_ASSERT( v == m_node_based_graph->GetTarget(forward_e1));
|
||||
const EdgeIterator reverse_e1 = m_node_based_graph->FindEdge(w, v);
|
||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != reverse_e1 );
|
||||
BOOST_ASSERT( v == m_node_based_graph->GetTarget(reverse_e1));
|
||||
|
||||
const EdgeData & fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
|
||||
const EdgeData & rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
|
||||
|
||||
if(
|
||||
( m_node_based_graph->FindEdge(u, w) != m_node_based_graph->EndEdges(u) ) ||
|
||||
( m_node_based_graph->FindEdge(w, u) != m_node_based_graph->EndEdges(w) )
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( //TODO: rename to IsCompatibleTo
|
||||
fwd_edge_data1.IsEqualTo(fwd_edge_data2) &&
|
||||
rev_edge_data1.IsEqualTo(rev_edge_data2)
|
||||
) {
|
||||
//Get distances before graph is modified
|
||||
const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance;
|
||||
const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance;
|
||||
|
||||
BOOST_ASSERT( 0 != forward_weight1 );
|
||||
BOOST_ASSERT( 0 != forward_weight2 );
|
||||
|
||||
const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance;
|
||||
const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance;
|
||||
|
||||
BOOST_ASSERT( 0 != reverse_weight1 );
|
||||
BOOST_ASSERT( 0 != forward_weight2 );
|
||||
|
||||
const bool add_traffic_signal_penalty = (m_traffic_lights.find(v) != m_traffic_lights.end());
|
||||
|
||||
// add weight of e2's to e1
|
||||
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
||||
m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
|
||||
if (add_traffic_signal_penalty)
|
||||
{
|
||||
m_node_based_graph->GetEdgeData(forward_e1).distance += speed_profile.trafficSignalPenalty;
|
||||
m_node_based_graph->GetEdgeData(reverse_e1).distance += speed_profile.trafficSignalPenalty;
|
||||
}
|
||||
|
||||
// extend e1's to targets of e2's
|
||||
m_node_based_graph->SetTarget(forward_e1, w);
|
||||
m_node_based_graph->SetTarget(reverse_e1, u);
|
||||
|
||||
// remove e2's (if bidir, otherwise only one)
|
||||
m_node_based_graph->DeleteEdge(v, forward_e2);
|
||||
m_node_based_graph->DeleteEdge(v, reverse_e2);
|
||||
|
||||
// update any involved turn restrictions
|
||||
FixupStartingTurnRestriction( u, v, w );
|
||||
FixupArrivingTurnRestriction( u, v, w );
|
||||
|
||||
FixupStartingTurnRestriction( w, v, u );
|
||||
FixupArrivingTurnRestriction( w, v, u );
|
||||
|
||||
// store compressed geometry in container
|
||||
m_geometry_compressor.CompressEdge(
|
||||
forward_e1,
|
||||
forward_e2,
|
||||
v,
|
||||
w,
|
||||
forward_weight1 + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty :0),
|
||||
forward_weight2
|
||||
);
|
||||
m_geometry_compressor.CompressEdge(
|
||||
reverse_e1,
|
||||
reverse_e2,
|
||||
v,
|
||||
u,
|
||||
reverse_weight1 ,
|
||||
reverse_weight2 + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty :0)
|
||||
);
|
||||
++removed_node_count;
|
||||
|
||||
BOOST_ASSERT
|
||||
(
|
||||
m_node_based_graph->GetEdgeData(forward_e1).nameID ==
|
||||
m_node_based_graph->GetEdgeData(reverse_e1).nameID
|
||||
);
|
||||
}
|
||||
}
|
||||
SimpleLogger().Write() << "removed " << removed_node_count << " nodes";
|
||||
m_geometry_compressor.PrintStatistics();
|
||||
|
||||
unsigned new_node_count = 0;
|
||||
unsigned new_edge_count = 0;
|
||||
for( unsigned i = 0; i < m_node_based_graph->GetNumberOfNodes(); ++i ) {
|
||||
if( m_node_based_graph->GetOutDegree(i) > 0 ) {
|
||||
++new_node_count;
|
||||
new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i));
|
||||
}
|
||||
}
|
||||
SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count;
|
||||
SimpleLogger().Write() << "Node compression ratio: " << new_node_count/(double)original_number_of_nodes;
|
||||
SimpleLogger().Write() << "Edge compression ratio: " << new_edge_count/(double)original_number_of_edges;
|
||||
|
||||
// renumber edge based node IDs
|
||||
unsigned numbered_edges_count = 0;
|
||||
for(NodeID current_node = 0; current_node < m_node_based_graph->GetNumberOfNodes(); ++current_node) {
|
||||
for(EdgeIterator current_edge = m_node_based_graph->BeginEdges(current_node); current_edge < m_node_based_graph->EndEdges(current_node); ++current_edge) {
|
||||
EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge);
|
||||
if( !edge_data.forward ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT( numbered_edges_count < m_node_based_graph->GetNumberOfEdges() );
|
||||
edge_data.edgeBasedNodeID = numbered_edges_count;
|
||||
++numbered_edges_count;
|
||||
|
||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != edge_data.edgeBasedNodeID);
|
||||
}
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "Identifying components of the road network";
|
||||
|
||||
unsigned skipped_turns_counter = 0;
|
||||
unsigned node_based_edge_counter = 0;
|
||||
unsigned original_edges_counter = 0;
|
||||
|
||||
std::ofstream edge_data_file(
|
||||
original_edge_data_filename,
|
||||
original_edge_data_filename.c_str(),
|
||||
std::ios::binary
|
||||
);
|
||||
|
||||
@@ -261,49 +642,62 @@ void EdgeBasedGraphFactory::Run(
|
||||
|
||||
//Run a BFS on the undirected graph and identify small components
|
||||
std::vector<unsigned> component_index_list;
|
||||
std::vector<NodeID> component_index_size;
|
||||
BFSCompentExplorer( component_index_list, component_index_size);
|
||||
std::vector<NodeID > component_index_size;
|
||||
BFSCompentExplorer( component_index_list, component_index_size );
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
"identified: " << component_index_size.size() << " many components";
|
||||
SimpleLogger().Write() <<
|
||||
"generating edge-expanded nodes";
|
||||
SimpleLogger().Write() << "generating edge-expanded nodes";
|
||||
|
||||
Percent p(m_node_based_graph->GetNumberOfNodes());
|
||||
//loop over all edges and generate new set of nodes.
|
||||
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||
|
||||
//loop over all edges and generate new set of nodes
|
||||
for(
|
||||
NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
|
||||
u < end;
|
||||
++u
|
||||
) {
|
||||
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
|
||||
BOOST_ASSERT( u < m_node_based_graph->GetNumberOfNodes() );
|
||||
p.printIncrement();
|
||||
for(
|
||||
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
|
||||
EdgeID e1 = m_node_based_graph->BeginEdges(u),
|
||||
last_edge = m_node_based_graph->EndEdges(u);
|
||||
e1 < last_edge;
|
||||
++e1
|
||||
) {
|
||||
NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||
const EdgeData & edge_data = m_node_based_graph->GetEdgeData(e1);
|
||||
if( edge_data.edgeBasedNodeID == SPECIAL_NODEID ) {
|
||||
// continue;
|
||||
}
|
||||
BOOST_ASSERT( e1 != SPECIAL_EDGEID );
|
||||
const NodeID v = m_node_based_graph->GetTarget(e1);
|
||||
|
||||
BOOST_ASSERT( SPECIAL_NODEID != v );
|
||||
// pick only every other edge
|
||||
if( u > v ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT( u < v );
|
||||
BOOST_ASSERT( edge_data.type != SHRT_MAX );
|
||||
|
||||
if(m_node_based_graph->GetEdgeData(e1).type != SHRT_MAX) {
|
||||
BOOST_ASSERT_MSG(e1 != UINT_MAX, "edge id invalid");
|
||||
BOOST_ASSERT_MSG(u != UINT_MAX, "souce node invalid");
|
||||
BOOST_ASSERT_MSG(v != UINT_MAX, "target node invalid");
|
||||
//Note: edges that end on barrier nodes or on a turn restriction
|
||||
//may actually be in two distinct components. We choose the smallest
|
||||
const unsigned size_of_component = std::min(
|
||||
component_index_size[component_index_list[u]],
|
||||
component_index_size[component_index_list[v]]
|
||||
);
|
||||
const unsigned size_of_component = std::min(
|
||||
component_index_size[component_index_list[u]],
|
||||
component_index_size[component_index_list[v]]
|
||||
);
|
||||
|
||||
InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 );
|
||||
}
|
||||
const bool component_is_tiny = ( size_of_component < 1000 );
|
||||
InsertEdgeBasedNode( u, v, e1, component_is_tiny );
|
||||
}
|
||||
}
|
||||
|
||||
SimpleLogger().Write()
|
||||
<< "Generated " << m_edge_based_node_list.size() << " nodes in " <<
|
||||
"edge-expanded graph";
|
||||
m_number_of_edge_based_nodes = numbered_edges_count;
|
||||
|
||||
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() <<
|
||||
" nodes in edge-expanded graph";
|
||||
SimpleLogger().Write() << "generating edge-expanded edges";
|
||||
|
||||
std::vector<NodeID>().swap(component_index_size);
|
||||
@@ -322,18 +716,19 @@ void EdgeBasedGraphFactory::Run(
|
||||
//Loop over all turns and generate new set of edges.
|
||||
//Three nested loop look super-linear, but we are dealing with a (kind of)
|
||||
//linear number of turns only.
|
||||
unsigned restricted_turns_counter = 0;
|
||||
unsigned skipped_uturns_counter = 0;
|
||||
unsigned skipped_barrier_turns_counter = 0;
|
||||
unsigned compressed = 0;
|
||||
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||
for(
|
||||
NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
|
||||
u < end;
|
||||
++u
|
||||
) {
|
||||
for(
|
||||
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
|
||||
last_edge_u = m_node_based_graph->EndEdges(u);
|
||||
e1 < last_edge_u;
|
||||
++e1
|
||||
) {
|
||||
for (NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
|
||||
{
|
||||
for (EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge_u = m_node_based_graph->EndEdges(u); e1 < last_edge_u; ++e1)
|
||||
{
|
||||
if( !m_node_based_graph->GetEdgeData(e1).forward ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++node_based_edge_counter;
|
||||
const NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||
@@ -345,83 +740,92 @@ void EdgeBasedGraphFactory::Run(
|
||||
e2 < last_edge_v;
|
||||
++e2
|
||||
) {
|
||||
if (!m_node_based_graph->GetEdgeData(e2).forward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const NodeIterator w = m_node_based_graph->GetTarget(e2);
|
||||
if(
|
||||
to_node_of_only_restriction != UINT_MAX &&
|
||||
w != to_node_of_only_restriction
|
||||
) {
|
||||
|
||||
if ((to_node_of_only_restriction != SPECIAL_NODEID) && (w != to_node_of_only_restriction))
|
||||
{
|
||||
//We are at an only_-restriction but not at the right turn.
|
||||
++skipped_turns_counter;
|
||||
++restricted_turns_counter;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( is_barrier_node) {
|
||||
if(u != w) {
|
||||
++skipped_turns_counter;
|
||||
if (is_barrier_node)
|
||||
{
|
||||
if (u != w)
|
||||
{
|
||||
++skipped_barrier_turns_counter;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if ( (u == w) && (m_node_based_graph->GetOutDegree(v) > 1) ) {
|
||||
++skipped_turns_counter;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((u == w) && (m_node_based_graph->GetOutDegree(v) > 1))
|
||||
{
|
||||
++skipped_uturns_counter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//only add an edge if turn is not a U-turn except when it is
|
||||
//at the end of a dead-end street
|
||||
if (
|
||||
CheckIfTurnIsRestricted(u, v, w) &&
|
||||
(to_node_of_only_restriction == UINT_MAX) &&
|
||||
(w != to_node_of_only_restriction)
|
||||
) {
|
||||
++skipped_turns_counter;
|
||||
if (CheckIfTurnIsRestricted(u, v, w) && (to_node_of_only_restriction == SPECIAL_NODEID) && (w != to_node_of_only_restriction))
|
||||
{
|
||||
++restricted_turns_counter;
|
||||
continue;
|
||||
}
|
||||
|
||||
//only add an edge if turn is not prohibited
|
||||
const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1);
|
||||
const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2);
|
||||
const EdgeData & edge_data1 = m_node_based_graph->GetEdgeData(e1);
|
||||
const EdgeData & edge_data2 = m_node_based_graph->GetEdgeData(e2);
|
||||
|
||||
BOOST_ASSERT(
|
||||
edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges()
|
||||
);
|
||||
BOOST_ASSERT(
|
||||
edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges()
|
||||
);
|
||||
BOOST_ASSERT(
|
||||
edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID
|
||||
);
|
||||
BOOST_ASSERT( edge_data1.forward );
|
||||
BOOST_ASSERT( edge_data2.forward );
|
||||
BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
|
||||
BOOST_ASSERT(edge_data1.forward);
|
||||
BOOST_ASSERT(edge_data2.forward);
|
||||
|
||||
// the following is the core of the loop.
|
||||
unsigned distance = edge_data1.distance;
|
||||
if( m_traffic_lights.find(v) != m_traffic_lights.end() ) {
|
||||
if (m_traffic_lights.find(v) != m_traffic_lights.end())
|
||||
{
|
||||
distance += speed_profile.trafficSignalPenalty;
|
||||
}
|
||||
const int turn_penalty = GetTurnPenalty(u, v, w, lua_state);
|
||||
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
|
||||
if(turnInstruction == TurnInstructions.UTurn){
|
||||
TurnInstruction turn_instruction = AnalyzeTurn(u, v, w);
|
||||
if (turn_instruction == TurnInstructionsClass::UTurn)
|
||||
{
|
||||
distance += speed_profile.uTurnPenalty;
|
||||
}
|
||||
distance += turn_penalty;
|
||||
|
||||
const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1);
|
||||
|
||||
if (edge_is_compressed)
|
||||
{
|
||||
++compressed;
|
||||
}
|
||||
|
||||
original_edge_data_vector.push_back(
|
||||
OriginalEdgeData(
|
||||
v,
|
||||
edge_data2.nameID,
|
||||
turnInstruction
|
||||
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v),
|
||||
edge_data1.nameID,
|
||||
turn_instruction,
|
||||
edge_is_compressed
|
||||
)
|
||||
);
|
||||
|
||||
++original_edges_counter;
|
||||
|
||||
if(original_edge_data_vector.size() > 100000) {
|
||||
FlushVectorToStream(
|
||||
edge_data_file,
|
||||
original_edge_data_vector
|
||||
);
|
||||
if (original_edge_data_vector.size() > 100000)
|
||||
{
|
||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||
}
|
||||
|
||||
BOOST_ASSERT( SPECIAL_NODEID != edge_data1.edgeBasedNodeID );
|
||||
BOOST_ASSERT( SPECIAL_NODEID != edge_data2.edgeBasedNodeID );
|
||||
|
||||
m_edge_based_edge_list.push_back(
|
||||
EdgeBasedEdge(
|
||||
edge_data1.edgeBasedNodeID,
|
||||
@@ -442,17 +846,16 @@ void EdgeBasedGraphFactory::Run(
|
||||
edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) );
|
||||
edge_data_file.close();
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
"Generated " << m_edge_based_node_list.size() << " edge based nodes";
|
||||
SimpleLogger().Write() <<
|
||||
"Node-based graph contains " << node_based_edge_counter << " edges";
|
||||
SimpleLogger().Write() <<
|
||||
"Edge-expanded graph ...";
|
||||
SimpleLogger().Write() <<
|
||||
" contains " << m_edge_based_edge_list.size() << " edges";
|
||||
SimpleLogger().Write() <<
|
||||
" skips " << skipped_turns_counter << " turns, "
|
||||
"defined by " << m_turn_restrictions_count << " restrictions";
|
||||
m_geometry_compressor.SerializeInternalVector( geometry_filename );
|
||||
|
||||
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes";
|
||||
SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges";
|
||||
SimpleLogger().Write() << "Edge-expanded graph ...";
|
||||
SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges";
|
||||
SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, "
|
||||
"defined by " << m_turn_restrictions_count << " restrictions";
|
||||
SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns";
|
||||
SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
|
||||
}
|
||||
|
||||
int EdgeBasedGraphFactory::GetTurnPenalty(
|
||||
@@ -488,7 +891,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
||||
const NodeID w
|
||||
) const {
|
||||
if(u == w) {
|
||||
return TurnInstructions.UTurn;
|
||||
return TurnInstructionsClass::UTurn;
|
||||
}
|
||||
|
||||
const EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
|
||||
@@ -498,10 +901,10 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
||||
const EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
|
||||
|
||||
if(!data1.contraFlow && data2.contraFlow) {
|
||||
return TurnInstructions.EnterAgainstAllowedDirection;
|
||||
return TurnInstructionsClass::EnterAgainstAllowedDirection;
|
||||
}
|
||||
if(data1.contraFlow && !data2.contraFlow) {
|
||||
return TurnInstructions.LeaveAgainstAllowedDirection;
|
||||
return TurnInstructionsClass::LeaveAgainstAllowedDirection;
|
||||
}
|
||||
|
||||
//roundabouts need to be handled explicitely
|
||||
@@ -509,19 +912,19 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
||||
//Is a turn possible? If yes, we stay on the roundabout!
|
||||
if( 1 == m_node_based_graph->GetOutDegree(v) ) {
|
||||
//No turn possible.
|
||||
return TurnInstructions.NoTurn;
|
||||
return TurnInstructionsClass::NoTurn;
|
||||
}
|
||||
return TurnInstructions.StayOnRoundAbout;
|
||||
return TurnInstructionsClass::StayOnRoundAbout;
|
||||
}
|
||||
//Does turn start or end on roundabout?
|
||||
if(data1.roundabout || data2.roundabout) {
|
||||
//We are entering the roundabout
|
||||
if( (!data1.roundabout) && data2.roundabout) {
|
||||
return TurnInstructions.EnterRoundAbout;
|
||||
return TurnInstructionsClass::EnterRoundAbout;
|
||||
}
|
||||
//We are leaving the roundabout
|
||||
if(data1.roundabout && (!data2.roundabout) ) {
|
||||
return TurnInstructions.LeaveRoundAbout;
|
||||
return TurnInstructionsClass::LeaveRoundAbout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,9 +934,9 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
||||
//TODO: Here we should also do a small graph exploration to check for
|
||||
// more complex situations
|
||||
if( 0 != data1.nameID ) {
|
||||
return TurnInstructions.NoTurn;
|
||||
return TurnInstructionsClass::NoTurn;
|
||||
} else if (m_node_based_graph->GetOutDegree(v) <= 2) {
|
||||
return TurnInstructions.NoTurn;
|
||||
return TurnInstructionsClass::NoTurn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,11 +945,11 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
||||
m_node_info_list[v],
|
||||
m_node_info_list[w]
|
||||
);
|
||||
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
|
||||
return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
|
||||
}
|
||||
|
||||
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
|
||||
return m_node_based_graph->GetNumberOfEdges();
|
||||
unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const {
|
||||
return m_number_of_edge_based_nodes;
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::BFSCompentExplorer(
|
||||
@@ -563,12 +966,12 @@ void EdgeBasedGraphFactory::BFSCompentExplorer(
|
||||
|
||||
component_index_list.resize(
|
||||
m_node_based_graph->GetNumberOfNodes(),
|
||||
UINT_MAX
|
||||
std::numeric_limits<unsigned>::max()
|
||||
);
|
||||
|
||||
//put unexplorered node with parent pointer into queue
|
||||
for( NodeID node = 0, end = m_node_based_graph->GetNumberOfNodes(); node < end; ++node) {
|
||||
if(UINT_MAX == component_index_list[node]) {
|
||||
if(std::numeric_limits<unsigned>::max() == component_index_list[node]) {
|
||||
bfs_queue.push(std::make_pair(node, node));
|
||||
//mark node as read
|
||||
component_index_list[node] = current_component;
|
||||
@@ -594,7 +997,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer(
|
||||
NodeIterator w = m_node_based_graph->GetTarget(e2);
|
||||
|
||||
if(
|
||||
to_node_of_only_restriction != UINT_MAX &&
|
||||
to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||
w != to_node_of_only_restriction
|
||||
) {
|
||||
// At an only_-restriction but not at the right turn
|
||||
@@ -605,7 +1008,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer(
|
||||
//when it is at the end of a dead-end street.
|
||||
if (!CheckIfTurnIsRestricted(u, v, w) ) {
|
||||
//only add an edge if turn is not prohibited
|
||||
if(UINT_MAX == component_index_list[w]) {
|
||||
if(std::numeric_limits<unsigned>::max() == component_index_list[w]) {
|
||||
//insert next (node, parent) only if w has
|
||||
//not yet been explored
|
||||
//mark node as read
|
||||
|
||||
@@ -53,23 +53,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iosfwd>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
class EdgeBasedGraphFactory : boost::noncopyable {
|
||||
public:
|
||||
struct SpeedProfileProperties{
|
||||
SpeedProfileProperties() :
|
||||
trafficSignalPenalty(0),
|
||||
uTurnPenalty(0),
|
||||
has_turn_penalty_function(false)
|
||||
{ }
|
||||
|
||||
int trafficSignalPenalty;
|
||||
int uTurnPenalty;
|
||||
bool has_turn_penalty_function;
|
||||
} speed_profile;
|
||||
struct SpeedProfileProperties;
|
||||
|
||||
explicit EdgeBasedGraphFactory(
|
||||
int number_of_nodes,
|
||||
@@ -78,10 +68,14 @@ public:
|
||||
std::vector<NodeID> & traffic_light_node_list,
|
||||
std::vector<TurnRestriction> & input_restrictions_list,
|
||||
std::vector<NodeInfo> & m_node_info_list,
|
||||
SpeedProfileProperties speed_profile
|
||||
SpeedProfileProperties & speed_profile
|
||||
);
|
||||
|
||||
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
|
||||
void Run(
|
||||
const std::string & original_edge_data_filename,
|
||||
const std::string & geometry_filename,
|
||||
lua_State *myLuaState
|
||||
);
|
||||
|
||||
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
||||
|
||||
@@ -100,10 +94,27 @@ public:
|
||||
lua_State *myLuaState
|
||||
) const;
|
||||
|
||||
unsigned GetNumberOfNodes() const;
|
||||
unsigned GetNumberOfEdgeBasedNodes() const;
|
||||
|
||||
struct SpeedProfileProperties{
|
||||
SpeedProfileProperties() :
|
||||
trafficSignalPenalty(0),
|
||||
uTurnPenalty(0),
|
||||
has_turn_penalty_function(false)
|
||||
{ }
|
||||
|
||||
int trafficSignalPenalty;
|
||||
int uTurnPenalty;
|
||||
bool has_turn_penalty_function;
|
||||
} speed_profile;
|
||||
|
||||
private:
|
||||
struct NodeBasedEdgeData {
|
||||
NodeBasedEdgeData() {
|
||||
//TODO: proper c'tor
|
||||
edgeBasedNodeID = UINT_MAX;
|
||||
}
|
||||
|
||||
int distance;
|
||||
unsigned edgeBasedNodeID;
|
||||
unsigned nameID;
|
||||
@@ -113,11 +124,26 @@ private:
|
||||
bool forward:1;
|
||||
bool backward:1;
|
||||
bool roundabout:1;
|
||||
bool ignoreInGrid:1;
|
||||
bool ignore_in_grid:1;
|
||||
bool contraFlow:1;
|
||||
|
||||
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) &&
|
||||
(contraFlow == other.contraFlow);
|
||||
}
|
||||
};
|
||||
|
||||
unsigned m_turn_restrictions_count;
|
||||
unsigned m_number_of_edge_based_nodes;
|
||||
|
||||
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
|
||||
@@ -139,6 +165,7 @@ private:
|
||||
boost::unordered_set<NodeID> m_traffic_lights;
|
||||
|
||||
RestrictionMap m_restriction_map;
|
||||
GeometryCompressor m_geometry_compressor;
|
||||
|
||||
NodeID CheckForEmanatingIsOnlyTurn(
|
||||
const NodeID u,
|
||||
@@ -152,9 +179,9 @@ private:
|
||||
) const;
|
||||
|
||||
void InsertEdgeBasedNode(
|
||||
NodeBasedDynamicGraph::EdgeIterator e1,
|
||||
NodeBasedDynamicGraph::NodeIterator u,
|
||||
NodeBasedDynamicGraph::NodeIterator v,
|
||||
NodeBasedDynamicGraph::EdgeIterator e1,
|
||||
bool belongsToTinyComponent
|
||||
);
|
||||
|
||||
@@ -167,6 +194,20 @@ private:
|
||||
std::ofstream & edge_data_file,
|
||||
std::vector<OriginalEdgeData> & original_edge_data_vector
|
||||
) const;
|
||||
|
||||
void FixupArrivingTurnRestriction(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
);
|
||||
|
||||
void FixupStartingTurnRestriction(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
);
|
||||
|
||||
unsigned max_id;
|
||||
};
|
||||
|
||||
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
||||
|
||||
@@ -26,69 +26,199 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "GeometryCompressor.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
int current_free_list_maximum = 0;
|
||||
int UniqueNumber () { return ++current_free_list_maximum; }
|
||||
int UniqueNumber() { return ++current_free_list_maximum; }
|
||||
|
||||
GeometryCompressor::GeometryCompressor() {
|
||||
m_free_list.resize(100);
|
||||
GeometryCompressor::GeometryCompressor()
|
||||
{
|
||||
m_free_list.reserve(100);
|
||||
IncreaseFreeList();
|
||||
}
|
||||
|
||||
void GeometryCompressor::IncreaseFreeList() {
|
||||
void GeometryCompressor::IncreaseFreeList()
|
||||
{
|
||||
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
||||
std::generate_n (m_free_list.rend(), 100, UniqueNumber);
|
||||
for (unsigned i = 100; i > 0; --i)
|
||||
{
|
||||
m_free_list.push_back(current_free_list_maximum);
|
||||
++current_free_list_maximum;
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryCompressor::AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id ) {
|
||||
//check if node_id already has a list
|
||||
boost::unordered_map<unsigned, unsigned>::const_iterator map_iterator;
|
||||
map_iterator = m_node_id_to_index_map.find( node_id );
|
||||
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
||||
{
|
||||
return (m_edge_id_to_list_index_map.find(edge_id) != m_edge_id_to_list_index_map.end());
|
||||
}
|
||||
|
||||
unsigned geometry_bucket_index = std::numeric_limits<unsigned>::max();
|
||||
if( m_node_id_to_index_map.end() == map_iterator ) {
|
||||
//if not, create one
|
||||
if( m_free_list.empty() ) {
|
||||
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
|
||||
{
|
||||
boost::unordered_map<EdgeID, unsigned>::const_iterator map_iterator;
|
||||
map_iterator = m_edge_id_to_list_index_map.find(edge_id);
|
||||
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
|
||||
BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
|
||||
return map_iterator->second;
|
||||
}
|
||||
|
||||
void GeometryCompressor::SerializeInternalVector(const std::string &path) const
|
||||
{
|
||||
|
||||
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary|std::ios::out);
|
||||
const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1;
|
||||
BOOST_ASSERT(UINT_MAX != number_of_compressed_geometries);
|
||||
geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned));
|
||||
|
||||
// write indices array
|
||||
unsigned prefix_sum_of_list_indices = 0;
|
||||
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
|
||||
{
|
||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||
|
||||
const std::vector<CompressedNode> ¤t_vector = m_compressed_geometries.at(i);
|
||||
const unsigned unpacked_size = current_vector.size();
|
||||
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
||||
prefix_sum_of_list_indices += unpacked_size;
|
||||
}
|
||||
// sentinel element
|
||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||
|
||||
// number of geometry entries to follow, it is the (inclusive) prefix sum
|
||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||
|
||||
unsigned control_sum = 0;
|
||||
// write compressed geometries
|
||||
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
|
||||
{
|
||||
const std::vector<CompressedNode> ¤t_vector = m_compressed_geometries[i];
|
||||
const unsigned unpacked_size = current_vector.size();
|
||||
control_sum += unpacked_size;
|
||||
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
||||
BOOST_FOREACH (const CompressedNode current_node, current_vector)
|
||||
{
|
||||
geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID));
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(control_sum == prefix_sum_of_list_indices);
|
||||
// all done, let's close the resource
|
||||
geometry_out_stream.close();
|
||||
}
|
||||
|
||||
void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
||||
const EdgeID edge_id_2,
|
||||
const NodeID via_node_id,
|
||||
const NodeID target_node_id,
|
||||
const EdgeWeight weight1,
|
||||
const EdgeWeight weight2)
|
||||
{
|
||||
// remove super-trivial geometries
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
||||
BOOST_ASSERT(std::numeric_limits<int>::max() != weight1);
|
||||
BOOST_ASSERT(std::numeric_limits<int>::max() != weight2);
|
||||
|
||||
// append list of removed edge_id plus via node to surviving edge id:
|
||||
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
|
||||
//
|
||||
// General scheme:
|
||||
// 1. append via node id to list of edge_id_1
|
||||
// 2. find list for edge_id_2, if yes add all elements and delete it
|
||||
|
||||
// Add via node id. List is created if it does not exist
|
||||
if (!HasEntryForID(edge_id_1))
|
||||
{
|
||||
// create a new entry in the map
|
||||
if (0 == m_free_list.size())
|
||||
{
|
||||
// make sure there is a place to put the entries
|
||||
IncreaseFreeList();
|
||||
}
|
||||
geometry_bucket_index = m_free_list.back();
|
||||
BOOST_ASSERT(!m_free_list.empty());
|
||||
m_edge_id_to_list_index_map[edge_id_1] = m_free_list.back();
|
||||
m_free_list.pop_back();
|
||||
} else {
|
||||
geometry_bucket_index = map_iterator->second;
|
||||
}
|
||||
|
||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != geometry_bucket_index );
|
||||
BOOST_ASSERT( geometry_bucket_index < m_compressed_geometries.size() );
|
||||
const unsigned edge_bucket_id1 = m_edge_id_to_list_index_map[edge_id_1];
|
||||
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
||||
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
|
||||
|
||||
//append contracted_node_id to m_compressed_geometries[node_id]
|
||||
m_compressed_geometries[geometry_bucket_index].push_back(contracted_node_id);
|
||||
std::vector<CompressedNode> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
|
||||
|
||||
//append m_compressed_geometries[contracted_node_id] to m_compressed_geometries[node_id]
|
||||
map_iterator = m_node_id_to_index_map.find(contracted_node_id);
|
||||
if ( m_node_id_to_index_map.end() != map_iterator) {
|
||||
const unsigned bucket_index_to_remove = map_iterator->second;
|
||||
BOOST_ASSERT( bucket_index_to_remove < m_compressed_geometries.size() );
|
||||
if (edge_bucket_list1.empty())
|
||||
{
|
||||
edge_bucket_list1.push_back(std::make_pair(via_node_id, weight1));
|
||||
}
|
||||
|
||||
m_compressed_geometries[geometry_bucket_index].insert(
|
||||
m_compressed_geometries[geometry_bucket_index].end(),
|
||||
m_compressed_geometries[bucket_index_to_remove].begin(),
|
||||
m_compressed_geometries[bucket_index_to_remove].end()
|
||||
);
|
||||
//remove m_compressed_geometries[contracted_node_id], add to free list
|
||||
m_compressed_geometries[bucket_index_to_remove].clear();
|
||||
m_free_list.push_back(bucket_index_to_remove);
|
||||
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
||||
BOOST_ASSERT(!edge_bucket_list1.empty());
|
||||
|
||||
if (HasEntryForID(edge_id_2))
|
||||
{
|
||||
// second edge is not atomic anymore
|
||||
const unsigned list_to_remove_index = GetPositionForID(edge_id_2);
|
||||
BOOST_ASSERT(list_to_remove_index < m_compressed_geometries.size());
|
||||
|
||||
std::vector<CompressedNode> &edge_bucket_list2 =
|
||||
m_compressed_geometries[list_to_remove_index];
|
||||
|
||||
// found an existing list, append it to the list of edge_id_1
|
||||
edge_bucket_list1.insert(
|
||||
edge_bucket_list1.end(), edge_bucket_list2.begin(), edge_bucket_list2.end());
|
||||
|
||||
// remove the list of edge_id_2
|
||||
m_edge_id_to_list_index_map.erase(edge_id_2);
|
||||
BOOST_ASSERT(m_edge_id_to_list_index_map.end() ==
|
||||
m_edge_id_to_list_index_map.find(edge_id_2));
|
||||
edge_bucket_list2.clear();
|
||||
BOOST_ASSERT(0 == edge_bucket_list2.size());
|
||||
m_free_list.push_back(list_to_remove_index);
|
||||
BOOST_ASSERT(list_to_remove_index == m_free_list.back());
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are certain that the second edge is atomic.
|
||||
edge_bucket_list1.push_back(std::make_pair(target_node_id, weight2));
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryCompressor::PrintStatistics() const {
|
||||
unsigned compressed_node_count = 0;
|
||||
const unsigned surviving_node_count = m_compressed_geometries.size();
|
||||
void GeometryCompressor::PrintStatistics() const
|
||||
{
|
||||
const uint64_t compressed_edges = m_compressed_geometries.size();
|
||||
BOOST_ASSERT(0 == compressed_edges % 2);
|
||||
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
|
||||
|
||||
BOOST_FOREACH(const std::vector<unsigned> & current_vector, m_compressed_geometries) {
|
||||
compressed_node_count += current_vector.size();
|
||||
uint64_t number_of_compressed_geometries = 0;
|
||||
uint64_t longest_chain_length = 0;
|
||||
BOOST_FOREACH (const std::vector<CompressedNode> ¤t_vector, m_compressed_geometries)
|
||||
{
|
||||
number_of_compressed_geometries += current_vector.size();
|
||||
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
||||
}
|
||||
SimpleLogger().Write() <<
|
||||
"surv: " << surviving_node_count <<
|
||||
", comp: " << compressed_node_count <<
|
||||
", comp ratio: " << ((float)surviving_node_count/std::max(compressed_node_count, 1u) );
|
||||
|
||||
SimpleLogger().Write() << "Geometry successfully removed:"
|
||||
"\n compressed edges: " << compressed_edges
|
||||
<< "\n compressed geometries: " << number_of_compressed_geometries
|
||||
<< "\n longest chain length: " << longest_chain_length
|
||||
<< "\n cmpr ratio: "
|
||||
<< ((float)compressed_edges /
|
||||
std::max(number_of_compressed_geometries, (uint64_t)1))
|
||||
<< "\n avg chain length: "
|
||||
<< (float)number_of_compressed_geometries /
|
||||
std::max((uint64_t)1, compressed_edges);
|
||||
}
|
||||
|
||||
const std::vector<GeometryCompressor::CompressedNode> &
|
||||
GeometryCompressor::GetBucketReference(const EdgeID edge_id) const
|
||||
{
|
||||
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
|
||||
return m_compressed_geometries.at(index);
|
||||
}
|
||||
|
||||
@@ -25,34 +25,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#ifndef GEOMETRY_COMPRESSOR_H
|
||||
#define GEOMETRY_COMPRESSOR_H
|
||||
|
||||
class GeometryCompressor {
|
||||
public:
|
||||
class GeometryCompressor
|
||||
{
|
||||
public:
|
||||
typedef std::pair<NodeID, EdgeWeight> CompressedNode;
|
||||
|
||||
GeometryCompressor();
|
||||
void AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id );
|
||||
void CompressEdge(const EdgeID surviving_edge_id,
|
||||
const EdgeID removed_edge_id,
|
||||
const NodeID via_node_id,
|
||||
const NodeID target_node,
|
||||
const EdgeWeight weight1,
|
||||
const EdgeWeight weight2);
|
||||
|
||||
bool HasEntryForID(const EdgeID edge_id) const;
|
||||
void PrintStatistics() const;
|
||||
void SerializeInternalVector(const std::string &path) const;
|
||||
unsigned GetPositionForID(const EdgeID edge_id) const;
|
||||
const std::vector<GeometryCompressor::CompressedNode> &
|
||||
GetBucketReference(const EdgeID edge_id) const;
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
void IncreaseFreeList();
|
||||
|
||||
std::vector<std::vector<unsigned> > m_compressed_geometries;
|
||||
std::vector<std::vector<CompressedNode> > m_compressed_geometries;
|
||||
std::vector<unsigned> m_free_list;
|
||||
boost::unordered_map<unsigned, unsigned> m_node_id_to_index_map;
|
||||
boost::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
||||
};
|
||||
|
||||
|
||||
#endif //GEOMETRY_COMPRESSOR_H
|
||||
#endif // GEOMETRY_COMPRESSOR_H
|
||||
|
||||
@@ -43,7 +43,7 @@ template< typename NodeID, typename Key >
|
||||
class ArrayStorage {
|
||||
public:
|
||||
|
||||
ArrayStorage( size_t size ) : positions( new Key[size] ) {
|
||||
explicit ArrayStorage( size_t size ) : positions( new Key[size] ) {
|
||||
memset(positions, 0, size*sizeof(Key));
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ template< typename NodeID, typename Key >
|
||||
class MapStorage {
|
||||
public:
|
||||
|
||||
MapStorage( size_t ) {}
|
||||
explicit MapStorage( size_t ) {}
|
||||
|
||||
Key &operator[]( NodeID node ) {
|
||||
return nodes[node];
|
||||
@@ -87,7 +87,7 @@ class UnorderedMapStorage {
|
||||
typedef typename UnorderedMapType::const_iterator UnorderedMapConstIterator;
|
||||
public:
|
||||
|
||||
UnorderedMapStorage( size_t ) {
|
||||
explicit UnorderedMapStorage( size_t ) {
|
||||
//hash table gets 1000 Buckets
|
||||
nodes.rehash(1000);
|
||||
}
|
||||
@@ -96,6 +96,11 @@ public:
|
||||
return nodes[node];
|
||||
}
|
||||
|
||||
Key const & operator[]( const NodeID node ) const {
|
||||
UnorderedMapConstIterator iter = nodes.find(node);
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
nodes.clear();
|
||||
}
|
||||
@@ -119,7 +124,7 @@ public:
|
||||
typedef Weight WeightType;
|
||||
typedef Data DataType;
|
||||
|
||||
BinaryHeap( size_t maxID )
|
||||
explicit BinaryHeap( size_t maxID )
|
||||
:
|
||||
nodeIndex( maxID )
|
||||
{
|
||||
@@ -158,6 +163,11 @@ public:
|
||||
return insertedNodes[index].data;
|
||||
}
|
||||
|
||||
Data const & GetData( NodeID node ) const {
|
||||
const Key index = nodeIndex[node];
|
||||
return insertedNodes[index].data;
|
||||
}
|
||||
|
||||
Weight& GetKey( NodeID node ) {
|
||||
const Key index = nodeIndex[node];
|
||||
return insertedNodes[index].weight;
|
||||
|
||||
@@ -40,7 +40,7 @@ template<typename Data>
|
||||
class ConcurrentQueue {
|
||||
|
||||
public:
|
||||
ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) { }
|
||||
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) { }
|
||||
|
||||
inline void push(const Data & data) {
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
|
||||
@@ -26,36 +26,54 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <cmath>
|
||||
#include <climits>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <bitset>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
: lat(INT_MIN),
|
||||
lon(INT_MIN)
|
||||
: 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(lat);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
|
||||
}
|
||||
if(0 != (std::abs(lon) >> 30))
|
||||
{
|
||||
std::bitset<32> x(lon);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Reset() {
|
||||
lat = INT_MIN;
|
||||
lon = INT_MIN;
|
||||
lat = std::numeric_limits<int>::min();
|
||||
lon = std::numeric_limits<int>::min();
|
||||
}
|
||||
bool FixedPointCoordinate::isSet() const {
|
||||
return (INT_MIN != lat) && (INT_MIN != lon);
|
||||
return (std::numeric_limits<int>::min() != lat) &&
|
||||
(std::numeric_limits<int>::min() != lon);
|
||||
}
|
||||
bool FixedPointCoordinate::isValid() const {
|
||||
if(
|
||||
lat > 90*COORDINATE_PRECISION ||
|
||||
if (lat > 90*COORDINATE_PRECISION ||
|
||||
lat < -90*COORDINATE_PRECISION ||
|
||||
lon > 180*COORDINATE_PRECISION ||
|
||||
lon < -180*COORDINATE_PRECISION
|
||||
) {
|
||||
lon < -180*COORDINATE_PRECISION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -70,10 +88,10 @@ double FixedPointCoordinate::ApproximateDistance(
|
||||
const int lat2,
|
||||
const int lon2
|
||||
) {
|
||||
BOOST_ASSERT(lat1 != INT_MIN);
|
||||
BOOST_ASSERT(lon1 != INT_MIN);
|
||||
BOOST_ASSERT(lat2 != INT_MIN);
|
||||
BOOST_ASSERT(lon2 != INT_MIN);
|
||||
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;
|
||||
@@ -93,25 +111,24 @@ double FixedPointCoordinate::ApproximateDistance(
|
||||
//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;
|
||||
double distance=earth*cHarv;
|
||||
return distance;
|
||||
return earth*cHarv;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(
|
||||
const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2
|
||||
) {
|
||||
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
|
||||
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon);
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2
|
||||
) {
|
||||
BOOST_ASSERT(c1.lat != INT_MIN);
|
||||
BOOST_ASSERT(c1.lon != INT_MIN);
|
||||
BOOST_ASSERT(c2.lat != INT_MIN);
|
||||
BOOST_ASSERT(c2.lon != INT_MIN);
|
||||
BOOST_ASSERT(c1.lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(c1.lon != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(c2.lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(c2.lon != std::numeric_limits<int>::min());
|
||||
const double RAD = 0.017453292519943295769236907684886;
|
||||
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
|
||||
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
|
||||
@@ -121,8 +138,7 @@ double FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
|
||||
const double y = (lat2-lat1);
|
||||
const double earthRadius = 6372797.560856;
|
||||
const double d = sqrt(x*x + y*y) * earthRadius;
|
||||
return d;
|
||||
return sqrt(x*x + y*y) * earthRadius;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalLatLonToString(
|
||||
@@ -160,3 +176,8 @@ void FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Output(std::ostream & out) const
|
||||
{
|
||||
out << "(" << lat/COORDINATE_PRECISION << "," << lon/COORDINATE_PRECISION << ")";
|
||||
}
|
||||
|
||||
@@ -96,10 +96,10 @@ public:
|
||||
DeallocatingVectorIterator() {}
|
||||
|
||||
template<typename T2>
|
||||
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
||||
explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
||||
|
||||
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
||||
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
||||
explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
||||
|
||||
template<typename T2>
|
||||
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
||||
|
||||
@@ -57,7 +57,7 @@ class DynamicGraph {
|
||||
};
|
||||
|
||||
//Constructs an empty graph with a given number of nodes.
|
||||
DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
||||
explicit DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
||||
m_nodes.reserve( m_numNodes );
|
||||
m_nodes.resize( m_numNodes );
|
||||
|
||||
|
||||
+127
-143
@@ -1,176 +1,160 @@
|
||||
#ifndef EDGE_BASED_NODE_H
|
||||
#define EDGE_BASED_NODE_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
// An EdgeBasedNode represents a node in the edge-expanded graph.
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct EdgeBasedNode {
|
||||
|
||||
EdgeBasedNode() :
|
||||
id(INT_MAX),
|
||||
lat1(INT_MAX),
|
||||
lat2(INT_MAX),
|
||||
lon1(INT_MAX),
|
||||
lon2(INT_MAX >> 1),
|
||||
belongsToTinyComponent(false),
|
||||
nameID(UINT_MAX),
|
||||
weight(UINT_MAX >> 1),
|
||||
ignoreInGrid(false)
|
||||
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() ),
|
||||
belongsToTinyComponent(false)
|
||||
{ }
|
||||
|
||||
// Computes:
|
||||
// - the distance from the given query location to nearest point on this edge (and returns it)
|
||||
// - the location on this edge which is nearest to the query location
|
||||
// - the ratio ps:pq, where p and q are the end points of this edge, and s is the perpendicular foot of
|
||||
// the query location on the line defined by p and q.
|
||||
double ComputePerpendicularDistance(
|
||||
const FixedPointCoordinate& query_location,
|
||||
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
|
||||
) :
|
||||
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),
|
||||
belongsToTinyComponent(belongs_to_tiny_component)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
( forward_edge_based_node_id != SPECIAL_NODEID ) ||
|
||||
( reverse_edge_based_node_id != SPECIAL_NODEID )
|
||||
);
|
||||
}
|
||||
|
||||
inline static double ComputePerpendicularDistance(
|
||||
const FixedPointCoordinate & coord_a,
|
||||
const FixedPointCoordinate & coord_b,
|
||||
const FixedPointCoordinate & query_location,
|
||||
FixedPointCoordinate & nearest_location,
|
||||
double & ratio,
|
||||
double precision = COORDINATE_PRECISION
|
||||
) const {
|
||||
double & r
|
||||
) {
|
||||
BOOST_ASSERT( query_location.isValid() );
|
||||
|
||||
const double epsilon = 1.0/precision;
|
||||
const double x = lat2y(query_location.lat/COORDINATE_PRECISION);
|
||||
const double y = query_location.lon/COORDINATE_PRECISION;
|
||||
const double a = lat2y(coord_a.lat/COORDINATE_PRECISION);
|
||||
const double b = coord_a.lon/COORDINATE_PRECISION;
|
||||
const double c = lat2y(coord_b.lat/COORDINATE_PRECISION);
|
||||
const double d = coord_b.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. + m*m);
|
||||
q = b + m*(p - a);
|
||||
} else {
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d*p - c*q)/(a*d - b*c);
|
||||
|
||||
if( ignoreInGrid ) {
|
||||
return std::numeric_limits<double>::max();
|
||||
//discretize the result to coordinate precision. it's a hack!
|
||||
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
|
||||
nY = 0.;
|
||||
}
|
||||
|
||||
// p, q : the end points of the underlying edge
|
||||
const Point p(lat2y(lat1/COORDINATE_PRECISION), lon1/COORDINATE_PRECISION);
|
||||
const Point q(lat2y(lat2/COORDINATE_PRECISION), lon2/COORDINATE_PRECISION);
|
||||
|
||||
// r : query location
|
||||
const Point r(lat2y(query_location.lat/COORDINATE_PRECISION),
|
||||
query_location.lon/COORDINATE_PRECISION);
|
||||
|
||||
const Point foot = ComputePerpendicularFoot(p, q, r, epsilon);
|
||||
ratio = ComputeRatio(p, q, foot, epsilon);
|
||||
|
||||
BOOST_ASSERT( !std::isnan(ratio) );
|
||||
|
||||
nearest_location = ComputeNearestPointOnSegment(foot, ratio);
|
||||
|
||||
r = (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(r) ) {
|
||||
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
|
||||
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
|
||||
r = 0.;
|
||||
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
|
||||
r = 1.;
|
||||
}
|
||||
BOOST_ASSERT( !std::isnan(r) );
|
||||
if( r <= 0. ){
|
||||
nearest_location.lat = coord_a.lat;
|
||||
nearest_location.lon = coord_a.lon;
|
||||
} else if( r >= 1. ){
|
||||
nearest_location.lat = coord_b.lat;
|
||||
nearest_location.lon = coord_b.lon;
|
||||
} else {
|
||||
// point lies in between
|
||||
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
|
||||
nearest_location.lon = q*COORDINATE_PRECISION;
|
||||
}
|
||||
BOOST_ASSERT( nearest_location.isValid() );
|
||||
|
||||
// TODO: Replace with euclidean approximation when k-NN search is done
|
||||
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(query_location, nearest_location);
|
||||
|
||||
BOOST_ASSERT( 0.0 <= approximated_distance );
|
||||
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
query_location,
|
||||
nearest_location
|
||||
);
|
||||
BOOST_ASSERT( 0. <= approximated_distance );
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
bool operator<(const EdgeBasedNode & other) const {
|
||||
return other.id < id;
|
||||
static inline FixedPointCoordinate Centroid(
|
||||
const FixedPointCoordinate & a,
|
||||
const FixedPointCoordinate & b
|
||||
) {
|
||||
FixedPointCoordinate centroid;
|
||||
//The coordinates of the midpoint are given by:
|
||||
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||
centroid.lon = (std::min(a.lon, b.lon) + std::max(a.lon, b.lon))/2;
|
||||
centroid.lat = (std::min(a.lat, b.lat) + std::max(a.lat, b.lat))/2;
|
||||
return centroid;
|
||||
}
|
||||
|
||||
bool operator==(const EdgeBasedNode & other) const {
|
||||
return id == other.id;
|
||||
}
|
||||
|
||||
// Returns the midpoint of the underlying edge.
|
||||
inline FixedPointCoordinate Centroid() const {
|
||||
return FixedPointCoordinate((lat1+lat2)/2, (lon1+lon2)/2);
|
||||
}
|
||||
|
||||
NodeID id;
|
||||
|
||||
// The coordinates of the end-points of the underlying edge.
|
||||
int lat1;
|
||||
int lat2;
|
||||
int lon1;
|
||||
int lon2:31;
|
||||
|
||||
bool belongsToTinyComponent:1;
|
||||
NodeID nameID;
|
||||
|
||||
// The weight of the underlying edge.
|
||||
unsigned weight:31;
|
||||
|
||||
bool ignoreInGrid:1;
|
||||
|
||||
private:
|
||||
|
||||
typedef std::pair<double,double> Point;
|
||||
|
||||
// Compute the perpendicular foot of point r on the line defined by p and q.
|
||||
Point ComputePerpendicularFoot(const Point &p, const Point &q, const Point &r, double epsilon) const {
|
||||
|
||||
// the projection of r onto the line pq
|
||||
double foot_x, foot_y;
|
||||
|
||||
const bool is_parallel_to_y_axis = std::abs(q.first - p.first) < epsilon;
|
||||
|
||||
if( is_parallel_to_y_axis ) {
|
||||
foot_x = q.first;
|
||||
foot_y = r.second;
|
||||
} else {
|
||||
// the slope of the line through (a|b) and (c|d)
|
||||
const double m = (q.second - p.second) / (q.first - p.first);
|
||||
|
||||
// Projection of (x|y) onto the line joining (a|b) and (c|d).
|
||||
foot_x = ((r.first + (m*r.second)) + (m*m*p.first - m*p.second))/(1.0 + m*m);
|
||||
foot_y = p.second + m*(foot_x - p.first);
|
||||
}
|
||||
|
||||
return Point(foot_x, foot_y);
|
||||
}
|
||||
|
||||
// Compute the ratio of the line segment pr to line segment pq.
|
||||
double ComputeRatio(const Point & p, const Point & q, const Point & r, double epsilon) const {
|
||||
|
||||
const bool is_parallel_to_x_axis = std::abs(q.second-p.second) < epsilon;
|
||||
const bool is_parallel_to_y_axis = std::abs(q.first -p.first ) < epsilon;
|
||||
|
||||
double ratio;
|
||||
|
||||
if( !is_parallel_to_y_axis ) {
|
||||
ratio = (r.first - p.first)/(q.first - p.first);
|
||||
} else if( !is_parallel_to_x_axis ) {
|
||||
ratio = (r.second - p.second)/(q.second - p.second);
|
||||
} else {
|
||||
// (a|b) and (c|d) are essentially the same point
|
||||
// by convention, we set the ratio to 0 in this case
|
||||
//ratio = ((lat2 == query_location.lat) && (lon2 == query_location.lon)) ? 1. : 0.;
|
||||
ratio = 0.0;
|
||||
}
|
||||
|
||||
// Round to integer if the ratio is close to 0 or 1.
|
||||
if( std::abs(ratio) <= epsilon ) {
|
||||
ratio = 0.0;
|
||||
} else if( std::abs(ratio-1.0) <= epsilon ) {
|
||||
ratio = 1.0;
|
||||
}
|
||||
|
||||
return ratio;
|
||||
}
|
||||
|
||||
// Computes the point on the segment pq which is nearest to a point r = p + lambda * (q-p).
|
||||
// p and q are the end points of the underlying edge.
|
||||
FixedPointCoordinate ComputeNearestPointOnSegment(const Point & r, double lambda) const {
|
||||
|
||||
if( lambda <= 0.0 ) {
|
||||
return FixedPointCoordinate(lat1, lon1);
|
||||
} else if( lambda >= 1.0 ) {
|
||||
return FixedPointCoordinate(lat2, lon2);
|
||||
}
|
||||
|
||||
// r lies between p and q
|
||||
return FixedPointCoordinate(
|
||||
y2lat(r.first)*COORDINATE_PRECISION,
|
||||
r.second*COORDINATE_PRECISION
|
||||
);
|
||||
bool IsCompressed() {
|
||||
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 belongsToTinyComponent;
|
||||
};
|
||||
|
||||
#endif //EDGE_BASED_NODE_H
|
||||
|
||||
+17
-12
@@ -28,41 +28,46 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef HASH_TABLE_H
|
||||
#define HASH_TABLE_H
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
template<typename KeyT, typename ValueT>
|
||||
class HashTable : public boost::unordered_map<KeyT, ValueT> {
|
||||
template<typename Key, typename Value, typename Hash = boost::hash<Key> >
|
||||
class HashTable : public boost::unordered_map<Key, Value> {
|
||||
private:
|
||||
typedef boost::unordered_map<KeyT, ValueT> super;
|
||||
typedef boost::unordered_map<Key, Value, Hash> super;
|
||||
public:
|
||||
static ValueT default_value;
|
||||
static Value default_value;
|
||||
|
||||
HashTable() : super() { }
|
||||
|
||||
HashTable(const unsigned size) : super(size) { }
|
||||
explicit HashTable(const unsigned size) : super(size) { }
|
||||
|
||||
inline void Add( KeyT const & key, ValueT const & value) {
|
||||
inline void Add( Key const & key, Value const & value) {
|
||||
super::emplace(std::make_pair(key, value));
|
||||
}
|
||||
|
||||
inline const ValueT Find(KeyT const & key) const {
|
||||
inline const Value Find(Key const & key) const
|
||||
{
|
||||
typename super::const_iterator iter = super::find(key);
|
||||
if( iter == super::end() ) {
|
||||
if (iter == super::end())
|
||||
{
|
||||
return boost::cref(default_value);
|
||||
}
|
||||
return boost::cref(iter->second);
|
||||
}
|
||||
|
||||
inline bool Holds( KeyT const & key) const {
|
||||
if( super::find(key) == super::end() ) {
|
||||
inline const bool Holds( Key const & key) const
|
||||
{
|
||||
if(super::find(key) == super::end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename KeyT, typename ValueT>
|
||||
ValueT HashTable<KeyT, ValueT>::default_value;
|
||||
template<typename Key, typename Value, typename Hash>
|
||||
Value HashTable<Key, Value, Hash>::default_value;
|
||||
|
||||
#endif /* HASH_TABLE_H */
|
||||
|
||||
@@ -61,7 +61,8 @@ public:
|
||||
bool ra,
|
||||
bool ig,
|
||||
bool ar,
|
||||
bool cf
|
||||
bool cf,
|
||||
bool is_split
|
||||
) : _source(s),
|
||||
_target(t),
|
||||
_name(n),
|
||||
@@ -72,7 +73,8 @@ public:
|
||||
_roundabout(ra),
|
||||
_ignoreInGrid(ig),
|
||||
_accessRestricted(ar),
|
||||
_contraFlow(cf)
|
||||
_contraFlow(cf),
|
||||
is_split(is_split)
|
||||
{
|
||||
if(ty < 0) {
|
||||
throw OSRMException("negative edge type");
|
||||
@@ -93,6 +95,7 @@ public:
|
||||
bool ignoreInGrid() const { return _ignoreInGrid; }
|
||||
bool isAccessRestricted() const { return _accessRestricted; }
|
||||
bool isContraFlow() const { return _contraFlow; }
|
||||
bool IsSplit() const { return is_split; }
|
||||
|
||||
//TODO: names need to be fixed.
|
||||
NodeID _source;
|
||||
@@ -106,6 +109,7 @@ public:
|
||||
bool _ignoreInGrid:1;
|
||||
bool _accessRestricted:1;
|
||||
bool _contraFlow:1;
|
||||
bool is_split:1;
|
||||
|
||||
private:
|
||||
NodeBasedEdge() { }
|
||||
@@ -129,7 +133,7 @@ public:
|
||||
}
|
||||
|
||||
template<class EdgeT>
|
||||
EdgeBasedEdge(const EdgeT & myEdge ) :
|
||||
explicit EdgeBasedEdge(const EdgeT & myEdge ) :
|
||||
m_source(myEdge.source),
|
||||
m_target(myEdge.target),
|
||||
m_edgeID(myEdge.data.via),
|
||||
@@ -162,7 +166,7 @@ public:
|
||||
m_weight(w),
|
||||
m_forward(f),
|
||||
m_backward(b)
|
||||
{}
|
||||
{ }
|
||||
|
||||
NodeID target() const { return m_target; }
|
||||
NodeID source() const { return m_source; }
|
||||
|
||||
@@ -44,11 +44,17 @@ struct ExternalMemoryNode : NodeInfo {
|
||||
bollard(bollard),
|
||||
trafficLight(traffic_light)
|
||||
{ }
|
||||
ExternalMemoryNode() : bollard(false), trafficLight(false) {}
|
||||
|
||||
ExternalMemoryNode()
|
||||
:
|
||||
bollard(false),
|
||||
trafficLight(false)
|
||||
{ }
|
||||
|
||||
static ExternalMemoryNode min_value() {
|
||||
return ExternalMemoryNode(0,0,0, false, false);
|
||||
}
|
||||
|
||||
static ExternalMemoryNode max_value() {
|
||||
return ExternalMemoryNode(
|
||||
std::numeric_limits<int>::max(),
|
||||
@@ -58,9 +64,11 @@ struct ExternalMemoryNode : NodeInfo {
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
NodeID key() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
bool bollard;
|
||||
bool trafficLight;
|
||||
};
|
||||
|
||||
@@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef INPUTREADERFACTORY_H
|
||||
#define INPUTREADERFACTORY_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <bzlib.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
@@ -51,21 +53,21 @@ int readFromBz2Stream( void* pointer, char* buffer, int len ) {
|
||||
return read;
|
||||
} else if(BZ_STREAM_END == context->error) {
|
||||
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
||||
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadGetUnused" <<std::endl; exit(-1);};
|
||||
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);
|
||||
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadClose" <<std::endl; exit(-1);};
|
||||
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);
|
||||
if(NULL == context->bz2){std::cerr << "Could not open file" <<std::endl; exit(-1);};
|
||||
BOOST_ASSERT_MSG(NULL != context->bz2, "Could not open file");
|
||||
}
|
||||
} else { std::cerr << "Could not read bz2 file" << std::endl; exit(-1); }
|
||||
} else { BOOST_ASSERT_MSG(false, "Could not read bz2 file"); }
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ private:
|
||||
std::list<CacheEntry> itemsInCache;
|
||||
boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap;
|
||||
public:
|
||||
LRUCache(unsigned c) : capacity(c) {}
|
||||
explicit LRUCache(unsigned c) : capacity(c) {}
|
||||
|
||||
bool Holds(KeyT key) {
|
||||
if(positionMap.find(key) != positionMap.end()) {
|
||||
|
||||
@@ -31,28 +31,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "TurnInstructions.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
|
||||
struct OriginalEdgeData{
|
||||
explicit OriginalEdgeData(
|
||||
NodeID via_node,
|
||||
unsigned name_id,
|
||||
TurnInstruction turn_instruction
|
||||
TurnInstruction turn_instruction,
|
||||
bool compressed_geometry
|
||||
) :
|
||||
via_node(via_node),
|
||||
name_id(name_id),
|
||||
turn_instruction(turn_instruction)
|
||||
via_node( via_node ),
|
||||
name_id( name_id ),
|
||||
turn_instruction( turn_instruction ),
|
||||
compressed_geometry( compressed_geometry )
|
||||
{ }
|
||||
|
||||
OriginalEdgeData() :
|
||||
via_node(UINT_MAX),
|
||||
name_id(UINT_MAX),
|
||||
turn_instruction(UCHAR_MAX)
|
||||
via_node( std::numeric_limits<unsigned>::max() ),
|
||||
name_id( std::numeric_limits<unsigned>::max() ),
|
||||
turn_instruction( std::numeric_limits<unsigned char>::max() ),
|
||||
compressed_geometry( false )
|
||||
{ }
|
||||
|
||||
NodeID via_node;
|
||||
unsigned name_id;
|
||||
TurnInstruction turn_instruction;
|
||||
bool compressed_geometry;
|
||||
};
|
||||
|
||||
#endif //ORIGINAL_EDGE_DATA_H
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
* @param maxValue the value that corresponds to 100%
|
||||
* @param step the progress is shown in steps of 'step' percent
|
||||
*/
|
||||
Percent(unsigned maxValue, unsigned step = 5) {
|
||||
explicit Percent(unsigned maxValue, unsigned step = 5) {
|
||||
reinit(maxValue, step);
|
||||
}
|
||||
|
||||
|
||||
+115
-45
@@ -29,75 +29,145 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define PHANTOMNODES_H_
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
struct PhantomNode {
|
||||
struct PhantomNode
|
||||
{
|
||||
PhantomNode() :
|
||||
edgeBasedNode(UINT_MAX),
|
||||
nodeBasedEdgeNameID(UINT_MAX),
|
||||
weight1(INT_MAX),
|
||||
weight2(INT_MAX),
|
||||
ratio(0.)
|
||||
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)
|
||||
{ }
|
||||
|
||||
NodeID edgeBasedNode;
|
||||
unsigned nodeBasedEdgeNameID;
|
||||
int weight1;
|
||||
int weight2;
|
||||
double ratio;
|
||||
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;
|
||||
void Reset() {
|
||||
edgeBasedNode = UINT_MAX;
|
||||
nodeBasedEdgeNameID = UINT_MAX;
|
||||
weight1 = INT_MAX;
|
||||
weight2 = INT_MAX;
|
||||
ratio = 0.;
|
||||
location.Reset();
|
||||
}
|
||||
bool isBidirected() const {
|
||||
return weight2 != INT_MAX;
|
||||
}
|
||||
bool isValid(const unsigned numberOfNodes) const {
|
||||
return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX);
|
||||
unsigned short fwd_segment_position;
|
||||
|
||||
int GetForwardWeightPlusOffset() const
|
||||
{
|
||||
if (SPECIAL_NODEID == forward_node_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const int result = (forward_offset + forward_weight);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator==(const PhantomNode & other) const {
|
||||
int GetReverseWeightPlusOffset() const
|
||||
{
|
||||
if (SPECIAL_NODEID == reverse_node_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const int result = (reverse_offset + reverse_weight);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
forward_node_id = SPECIAL_NODEID;
|
||||
name_id = SPECIAL_NODEID;
|
||||
forward_weight = INVALID_EDGE_WEIGHT;
|
||||
reverse_weight = INVALID_EDGE_WEIGHT;
|
||||
forward_offset = 0;
|
||||
reverse_offset = 0;
|
||||
location.Reset();
|
||||
}
|
||||
|
||||
bool isBidirected() const
|
||||
{
|
||||
return (forward_node_id != SPECIAL_NODEID) &&
|
||||
(reverse_node_id != SPECIAL_NODEID);
|
||||
}
|
||||
|
||||
bool IsCompressed() const
|
||||
{
|
||||
return (forward_offset != 0) || (reverse_offset != 0);
|
||||
}
|
||||
|
||||
bool isValid(const unsigned numberOfNodes) const
|
||||
{
|
||||
return
|
||||
location.isValid() &&
|
||||
(
|
||||
(forward_node_id < numberOfNodes) ||
|
||||
(reverse_node_id < numberOfNodes)
|
||||
) &&
|
||||
(
|
||||
(forward_weight != INVALID_EDGE_WEIGHT) ||
|
||||
(reverse_weight != INVALID_EDGE_WEIGHT)
|
||||
) &&
|
||||
(name_id != std::numeric_limits<unsigned>::max()
|
||||
);
|
||||
}
|
||||
|
||||
bool operator==(const PhantomNode & other) const
|
||||
{
|
||||
return location == other.location;
|
||||
}
|
||||
};
|
||||
|
||||
struct PhantomNodes {
|
||||
PhantomNode startPhantom;
|
||||
PhantomNode targetPhantom;
|
||||
void Reset() {
|
||||
startPhantom.Reset();
|
||||
targetPhantom.Reset();
|
||||
struct PhantomNodes
|
||||
{
|
||||
PhantomNode source_phantom;
|
||||
PhantomNode target_phantom;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
source_phantom.Reset();
|
||||
target_phantom.Reset();
|
||||
}
|
||||
|
||||
bool PhantomsAreOnSameNodeBasedEdge() const {
|
||||
return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
|
||||
bool PhantomsAreOnSameNodeBasedEdge() const
|
||||
{
|
||||
return (source_phantom.forward_node_id == target_phantom.forward_node_id);
|
||||
}
|
||||
|
||||
bool AtLeastOnePhantomNodeIsUINTMAX() const {
|
||||
return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
|
||||
bool AtLeastOnePhantomNodeIsInvalid() const
|
||||
{
|
||||
return ((source_phantom.forward_node_id == SPECIAL_NODEID) && (source_phantom.reverse_node_id == SPECIAL_NODEID)) ||
|
||||
((target_phantom.forward_node_id == SPECIAL_NODEID) && (target_phantom.reverse_node_id == SPECIAL_NODEID));
|
||||
}
|
||||
|
||||
bool PhantomNodesHaveEqualLocation() const {
|
||||
return startPhantom == targetPhantom;
|
||||
bool PhantomNodesHaveEqualLocation() const
|
||||
{
|
||||
return source_phantom == target_phantom;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
|
||||
out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl;
|
||||
out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl;
|
||||
out << "startCoord: " << pn.startPhantom.location << std::endl;
|
||||
out << "targetCoord: " << pn.targetPhantom.location << std::endl;
|
||||
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 << "node: " << pn.edgeBasedNode << ", name: " << pn.nodeBasedEdgeNameID << ", w1: " << pn.weight1 << ", w2: " << pn.weight2 << ", ratio: " << pn.ratio << ", loc: " << pn.location;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
struct QueryEdge {
|
||||
NodeID source;
|
||||
NodeID target;
|
||||
|
||||
+14
-13
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _NODE_COORDS_H
|
||||
#define _NODE_COORDS_H
|
||||
#ifndef QUERY_NODE_H
|
||||
#define QUERY_NODE_H
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
@@ -34,17 +34,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <climits>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct NodeInfo {
|
||||
typedef NodeID key_type; //type of NodeID
|
||||
typedef int value_type; //type of lat,lons
|
||||
|
||||
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
|
||||
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
|
||||
NodeInfo(int lat, int lon, NodeID id) : lat(lat), lon(lon), id(id) { }
|
||||
NodeInfo()
|
||||
:
|
||||
lat(std::numeric_limits<int>::max()),
|
||||
lon(std::numeric_limits<int>::max()),
|
||||
id(std::numeric_limits<unsigned>::max())
|
||||
{ }
|
||||
|
||||
int lat;
|
||||
int lon;
|
||||
NodeID id;
|
||||
@@ -69,18 +72,16 @@ struct NodeInfo {
|
||||
switch(n) {
|
||||
case 1:
|
||||
return lat;
|
||||
break;
|
||||
// break;
|
||||
case 0:
|
||||
return lon;
|
||||
break;
|
||||
// break;
|
||||
default:
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
return UINT_MAX;
|
||||
break;
|
||||
}
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
return UINT_MAX;
|
||||
return std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
};
|
||||
|
||||
#endif //_NODE_COORDS_H
|
||||
#endif //QUERY_NODE_H
|
||||
|
||||
@@ -70,10 +70,19 @@ struct RawRouteData {
|
||||
unsigned checkSum;
|
||||
int lengthOfShortestPath;
|
||||
int lengthOfAlternativePath;
|
||||
bool source_traversed_in_reverse;
|
||||
bool target_traversed_in_reverse;
|
||||
bool alt_source_traversed_in_reverse;
|
||||
bool alt_target_traversed_in_reverse;
|
||||
|
||||
RawRouteData() :
|
||||
checkSum(UINT_MAX),
|
||||
lengthOfShortestPath(INT_MAX),
|
||||
lengthOfAlternativePath(INT_MAX)
|
||||
lengthOfAlternativePath(INT_MAX),
|
||||
source_traversed_in_reverse(false),
|
||||
target_traversed_in_reverse(false),
|
||||
alt_source_traversed_in_reverse(false),
|
||||
alt_target_traversed_in_reverse(false)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define RESTRICTION_H_
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include <climits>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct TurnRestriction {
|
||||
NodeID viaNode;
|
||||
@@ -58,14 +59,13 @@ struct TurnRestriction {
|
||||
bool unused7:1;
|
||||
} flags;
|
||||
|
||||
TurnRestriction(NodeID viaNode) :
|
||||
explicit TurnRestriction(NodeID viaNode) :
|
||||
viaNode(viaNode),
|
||||
fromNode(UINT_MAX),
|
||||
toNode(UINT_MAX) {
|
||||
|
||||
fromNode(std::numeric_limits<unsigned>::max()),
|
||||
toNode(std::numeric_limits<unsigned>::max()) {
|
||||
}
|
||||
|
||||
TurnRestriction(const bool isOnly = false) :
|
||||
explicit TurnRestriction(const bool isOnly = false) :
|
||||
viaNode(UINT_MAX),
|
||||
fromNode(UINT_MAX),
|
||||
toNode(UINT_MAX) {
|
||||
@@ -91,12 +91,12 @@ struct InputRestrictionContainer {
|
||||
{
|
||||
restriction.viaNode = vn;
|
||||
}
|
||||
InputRestrictionContainer(
|
||||
explicit InputRestrictionContainer(
|
||||
bool isOnly = false
|
||||
) :
|
||||
fromWay(UINT_MAX),
|
||||
toWay(UINT_MAX),
|
||||
viaNode(UINT_MAX)
|
||||
fromWay(std::numeric_limits<unsigned>::max()),
|
||||
toWay(std::numeric_limits<unsigned>::max()),
|
||||
viaNode(std::numeric_limits<unsigned>::max())
|
||||
{
|
||||
restriction.flags.isOnly = isOnly;
|
||||
}
|
||||
@@ -106,10 +106,10 @@ struct InputRestrictionContainer {
|
||||
}
|
||||
static InputRestrictionContainer max_value() {
|
||||
return InputRestrictionContainer(
|
||||
UINT_MAX,
|
||||
UINT_MAX,
|
||||
UINT_MAX,
|
||||
UINT_MAX
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||
AlternativeRouting <DataFacadeT> alternative_path;
|
||||
|
||||
SearchEngine( DataFacadeT * facade )
|
||||
explicit SearchEngine( DataFacadeT * facade )
|
||||
:
|
||||
facade (facade),
|
||||
shortest_path (facade, engine_working_data),
|
||||
|
||||
@@ -41,7 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
struct _HeapData {
|
||||
NodeID parent;
|
||||
_HeapData( NodeID p ) : parent(p) { }
|
||||
/* explicit */ _HeapData( NodeID p ) : parent(p) { }
|
||||
};
|
||||
|
||||
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||
|
||||
@@ -41,7 +41,7 @@ template<typename DataT>
|
||||
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
|
||||
DataT * p;
|
||||
public:
|
||||
ShMemIterator(DataT * x) : p(x) {}
|
||||
explicit ShMemIterator(DataT * x) : p(x) {}
|
||||
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {}
|
||||
ShMemIterator& operator++() {
|
||||
++p;
|
||||
@@ -115,6 +115,8 @@ public:
|
||||
|
||||
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];
|
||||
@@ -126,6 +128,63 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class SharedMemoryWrapper<bool> {
|
||||
private:
|
||||
unsigned * m_ptr;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
SharedMemoryWrapper() :
|
||||
m_ptr(NULL),
|
||||
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 );
|
||||
}
|
||||
|
||||
// void SetData(const DataT * ptr, const std::size_t size) {
|
||||
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
|
||||
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
|
||||
// m_ptr.reset(ptr);
|
||||
// m_size = size;
|
||||
// }
|
||||
|
||||
bool at(const std::size_t index) const {
|
||||
// BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||
const unsigned bucket = index / 32;
|
||||
const unsigned offset = index % 32;
|
||||
return m_ptr[bucket] & (1 << offset);
|
||||
}
|
||||
|
||||
// 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(); }
|
||||
|
||||
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 {
|
||||
typedef typename boost::conditional<
|
||||
@@ -135,5 +194,4 @@ struct ShM {
|
||||
>::type vector;
|
||||
};
|
||||
|
||||
|
||||
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||
|
||||
@@ -112,16 +112,18 @@ public:
|
||||
if(eid2 == UINT_MAX) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"cannot find first segment of edge (" <<
|
||||
u << "," << data.id << "," << v << ")";
|
||||
u << "," << data.id << "," << v << "), eid: " << eid;
|
||||
|
||||
data.shortcut = false;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
eid2 = FindEdgeInEitherDirection(data.id, v);
|
||||
if(eid2 == UINT_MAX) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"cannot find second segment of edge (" <<
|
||||
u << "," << data.id << "," << v << ")";
|
||||
u << "," << data.id << "," << v << "), eid2: " << eid2;
|
||||
data.shortcut = false;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,17 +157,17 @@ public:
|
||||
}
|
||||
|
||||
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
||||
return EdgeIterator( _nodes[n].firstEdge );
|
||||
return EdgeIterator( _nodes.at(n).firstEdge );
|
||||
}
|
||||
|
||||
EdgeIterator EndEdges( const NodeIterator n ) const {
|
||||
return EdgeIterator( _nodes[n+1].firstEdge );
|
||||
return EdgeIterator( _nodes.at(n+1).firstEdge );
|
||||
}
|
||||
|
||||
//searches for a specific edge
|
||||
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
||||
EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
||||
EdgeWeight smallestWeight = UINT_MAX;
|
||||
EdgeWeight smallestWeight = INVALID_EDGE_WEIGHT;
|
||||
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
||||
const NodeID target = GetTarget(edge);
|
||||
const EdgeWeight weight = GetEdgeData(edge).distance;
|
||||
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
StaticKDTree( std::vector< InputPoint > * points ){
|
||||
explicit StaticKDTree( std::vector< InputPoint > * points ){
|
||||
BOOST_ASSERT( k > 0 );
|
||||
BOOST_ASSERT ( points->size() > 0 );
|
||||
size = points->size();
|
||||
@@ -207,7 +207,7 @@ private:
|
||||
};
|
||||
class Less {
|
||||
public:
|
||||
Less( unsigned d ) {
|
||||
explicit Less( unsigned d ) {
|
||||
dimension = d;
|
||||
BOOST_ASSERT( dimension < k );
|
||||
}
|
||||
|
||||
+101
-210
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "DeallocatingVector.h"
|
||||
#include "HilbertValue.h"
|
||||
#include "PhantomNodes.h"
|
||||
#include "QueryNode.h"
|
||||
#include "SharedMemoryFactory.h"
|
||||
#include "SharedMemoryVectorWrapper.h"
|
||||
|
||||
@@ -51,6 +52,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/algorithm/minmax_element.hpp>
|
||||
#include <boost/range/algorithm_ext/erase.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
@@ -68,7 +70,7 @@ const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
|
||||
|
||||
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
|
||||
|
||||
template<class DataT, bool UseSharedMemory = false>
|
||||
template<class DataT, class CoordinateListT = std::vector<FixedPointCoordinate>, bool UseSharedMemory = false>
|
||||
class StaticRTree : boost::noncopyable {
|
||||
public:
|
||||
struct RectangleInt2D {
|
||||
@@ -82,22 +84,35 @@ public:
|
||||
int32_t min_lat, max_lat;
|
||||
|
||||
inline void InitializeMBRectangle(
|
||||
const DataT * objects,
|
||||
const uint32_t element_count
|
||||
DataT const * objects,
|
||||
const uint32_t element_count,
|
||||
const std::vector<NodeInfo> & coordinate_list
|
||||
) {
|
||||
for(uint32_t i = 0; i < element_count; ++i) {
|
||||
min_lon = std::min(
|
||||
min_lon, std::min(objects[i].lon1, objects[i].lon2)
|
||||
min_lon, std::min(
|
||||
coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
max_lon = std::max(
|
||||
max_lon, std::max(objects[i].lon1, objects[i].lon2)
|
||||
max_lon, std::max(
|
||||
coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
|
||||
min_lat = std::min(
|
||||
min_lat, std::min(objects[i].lat1, objects[i].lat2)
|
||||
min_lat, std::min(
|
||||
coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
max_lat = std::max(
|
||||
max_lat, std::max(objects[i].lat1, objects[i].lat2)
|
||||
max_lat, std::max(
|
||||
coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -221,9 +236,9 @@ public:
|
||||
}
|
||||
|
||||
inline bool Contains(const FixedPointCoordinate & location) const {
|
||||
bool lats_contained =
|
||||
const bool lats_contained =
|
||||
(location.lat > min_lat) && (location.lat < max_lat);
|
||||
bool lons_contained =
|
||||
const bool lons_contained =
|
||||
(location.lon > min_lon) && (location.lon < max_lon);
|
||||
return lats_contained && lons_contained;
|
||||
}
|
||||
@@ -289,21 +304,23 @@ private:
|
||||
|
||||
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
|
||||
uint64_t m_element_count;
|
||||
|
||||
const std::string m_leaf_node_filename;
|
||||
boost::shared_ptr<CoordinateListT> m_coordinate_list;
|
||||
|
||||
public:
|
||||
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
|
||||
explicit StaticRTree(
|
||||
std::vector<DataT> & input_data_vector,
|
||||
const std::string tree_node_filename,
|
||||
const std::string leaf_node_filename
|
||||
const std::string leaf_node_filename,
|
||||
const std::vector<NodeInfo> & coordinate_list
|
||||
)
|
||||
: m_element_count(input_data_vector.size()),
|
||||
m_leaf_node_filename(leaf_node_filename)
|
||||
{
|
||||
SimpleLogger().Write() <<
|
||||
"constructing r-tree of " << m_element_count <<
|
||||
" elements";
|
||||
" edge elements build on-top of " << coordinate_list.size() << " coordinates";
|
||||
|
||||
double time1 = get_timestamp();
|
||||
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
|
||||
@@ -315,8 +332,17 @@ public:
|
||||
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
|
||||
input_wrapper_vector[element_counter].m_array_index = element_counter;
|
||||
//Get Hilbert-Value for centroid in mercartor projection
|
||||
DataT & current_element = input_data_vector[element_counter];
|
||||
FixedPointCoordinate current_centroid = current_element.Centroid();
|
||||
DataT const & current_element = input_data_vector[element_counter];
|
||||
FixedPointCoordinate current_centroid = DataT::Centroid(
|
||||
FixedPointCoordinate(
|
||||
coordinate_list.at(current_element.u).lat,
|
||||
coordinate_list.at(current_element.u).lon
|
||||
),
|
||||
FixedPointCoordinate(
|
||||
coordinate_list.at(current_element.v).lat,
|
||||
coordinate_list.at(current_element.v).lon
|
||||
)
|
||||
);
|
||||
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
|
||||
|
||||
uint64_t current_hilbert_value = get_hilbert_number(current_centroid);
|
||||
@@ -347,7 +373,11 @@ public:
|
||||
}
|
||||
|
||||
//generate tree node that resemble the objects in leaf and store it for next level
|
||||
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
|
||||
current_node.minimum_bounding_rectangle.InitializeMBRectangle(
|
||||
current_leaf.objects,
|
||||
current_leaf.object_count,
|
||||
coordinate_list
|
||||
);
|
||||
current_node.child_is_on_disk = true;
|
||||
current_node.children[0] = tree_nodes_in_level.size();
|
||||
tree_nodes_in_level.push_back(current_node);
|
||||
@@ -426,9 +456,11 @@ public:
|
||||
//Read-only operation for queries
|
||||
explicit StaticRTree(
|
||||
const boost::filesystem::path & node_file,
|
||||
const boost::filesystem::path & leaf_file
|
||||
) : m_leaf_node_filename(leaf_file.string()) {
|
||||
const boost::filesystem::path & leaf_file,
|
||||
const boost::shared_ptr<CoordinateListT> coordinate_list
|
||||
) : m_leaf_node_filename( leaf_file.string() ) {
|
||||
//open tree node file and load into RAM.
|
||||
m_coordinate_list = coordinate_list;
|
||||
|
||||
if ( !boost::filesystem::exists( node_file ) ) {
|
||||
throw OSRMException("ram index file does not exist");
|
||||
@@ -463,9 +495,11 @@ public:
|
||||
explicit StaticRTree(
|
||||
TreeNode * tree_node_ptr,
|
||||
const uint32_t number_of_nodes,
|
||||
const boost::filesystem::path & leaf_file
|
||||
const boost::filesystem::path & leaf_file,
|
||||
boost::shared_ptr<CoordinateListT> coordinate_list
|
||||
) : m_search_tree(tree_node_ptr, number_of_nodes),
|
||||
m_leaf_node_filename(leaf_file.string())
|
||||
m_leaf_node_filename(leaf_file.string()),
|
||||
m_coordinate_list(coordinate_list)
|
||||
{
|
||||
//open leaf node file and store thread specific pointer
|
||||
if ( !boost::filesystem::exists( leaf_file ) ) {
|
||||
@@ -487,152 +521,7 @@ public:
|
||||
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||
}
|
||||
//Read-only operation for queries
|
||||
/*
|
||||
inline void FindKNearestPhantomNodesForCoordinate(
|
||||
const FixedPointCoordinate & location,
|
||||
const unsigned zoom_level,
|
||||
const unsigned candidate_count,
|
||||
std::vector<std::pair<PhantomNode, double> > & result_vector
|
||||
) const {
|
||||
|
||||
bool ignore_tiny_components = (zoom_level <= 14);
|
||||
DataT nearest_edge;
|
||||
|
||||
uint32_t io_count = 0;
|
||||
uint32_t explored_tree_nodes_count = 0;
|
||||
SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
double min_max_dist = std::numeric_limits<double>::max();
|
||||
bool found_a_nearest_edge = false;
|
||||
|
||||
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||
|
||||
//initialize queue with root element
|
||||
std::priority_queue<QueryCandidate> traversal_queue;
|
||||
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
|
||||
BOOST_ASSERT_MSG(std::numberic_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
|
||||
|
||||
while(!traversal_queue.empty()) {
|
||||
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||
|
||||
++explored_tree_nodes_count;
|
||||
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
||||
bool prune_upward = (current_query_node.min_dist >= min_dist);
|
||||
if( !prune_downward && !prune_upward ) { //downward pruning
|
||||
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||
if (current_tree_node.child_is_on_disk) {
|
||||
LeafNode current_leaf_node;
|
||||
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||
++io_count;
|
||||
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||
DataT & current_edge = current_leaf_node.objects[i];
|
||||
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double current_ratio = 0.;
|
||||
double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
|
||||
input_coordinate,
|
||||
nearest,
|
||||
current_ratio
|
||||
);
|
||||
|
||||
if(
|
||||
current_perpendicular_distance < min_dist
|
||||
&& !DoubleEpsilonCompare(
|
||||
current_perpendicular_distance,
|
||||
min_dist
|
||||
)
|
||||
) { //found a new minimum
|
||||
min_dist = current_perpendicular_distance;
|
||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||
result_phantom_node.weight1 = current_edge.weight;
|
||||
result_phantom_node.weight2 = INT_MAX;
|
||||
result_phantom_node.location = nearest;
|
||||
current_start_coordinate.lat = current_edge.lat1;
|
||||
current_start_coordinate.lon = current_edge.lon1;
|
||||
current_end_coordinate.lat = current_edge.lat2;
|
||||
current_end_coordinate.lon = current_edge.lon2;
|
||||
nearest_edge = current_edge;
|
||||
found_a_nearest_edge = true;
|
||||
} else if(
|
||||
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||
&& EdgesAreEquivalent(
|
||||
current_start_coordinate,
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat1,
|
||||
current_edge.lon1
|
||||
),
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat2,
|
||||
current_edge.lon2
|
||||
),
|
||||
current_end_coordinate
|
||||
)
|
||||
) {
|
||||
result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode);
|
||||
result_phantom_node.weight2 = current_edge.weight;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//traverse children, prune if global mindist is smaller than local one
|
||||
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
||||
const int32_t child_id = current_tree_node.children[i];
|
||||
TreeNode & child_tree_node = m_search_tree[child_id];
|
||||
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
||||
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
||||
if( current_min_max_dist < min_max_dist ) {
|
||||
min_max_dist = current_min_max_dist;
|
||||
}
|
||||
if (current_min_dist > min_max_dist) {
|
||||
continue;
|
||||
}
|
||||
if (current_min_dist > min_dist) { //upward pruning
|
||||
continue;
|
||||
}
|
||||
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const double distance_to_edge =
|
||||
ApproximateDistance (
|
||||
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||
result_phantom_node.location
|
||||
);
|
||||
|
||||
const double length_of_edge =
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||
FixedPointCoordinate(nearest_edge.lat2, nearest_edge.lon2)
|
||||
);
|
||||
|
||||
const double ratio = (found_a_nearest_edge ?
|
||||
std::min(1., distance_to_edge/ length_of_edge ) : 0 );
|
||||
result_phantom_node.weight1 *= ratio;
|
||||
if(INT_MAX != result_phantom_node.weight2) {
|
||||
result_phantom_node.weight2 *= (1.-ratio);
|
||||
}
|
||||
result_phantom_node.ratio = ratio;
|
||||
|
||||
//Hack to fix rounding errors and wandering via nodes.
|
||||
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
|
||||
result_phantom_node.location.lon = input_coordinate.lon;
|
||||
}
|
||||
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "mindist: " << min_distphantom_node.isBidirected() ? "yes" : "no");
|
||||
return found_a_nearest_edge;
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
bool LocateClosestEndPointForCoordinate(
|
||||
const FixedPointCoordinate & input_coordinate,
|
||||
FixedPointCoordinate & result_coordinate,
|
||||
@@ -671,7 +560,7 @@ public:
|
||||
current_leaf_node
|
||||
);
|
||||
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||
const DataT & current_edge = current_leaf_node.objects[i];
|
||||
DataT const & current_edge = current_leaf_node.objects[i];
|
||||
if(
|
||||
ignore_tiny_components &&
|
||||
current_edge.belongsToTinyComponent
|
||||
@@ -682,29 +571,29 @@ public:
|
||||
double current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
current_edge.lat1,
|
||||
current_edge.lon1
|
||||
m_coordinate_list->at(current_edge.u).lat,
|
||||
m_coordinate_list->at(current_edge.u).lon
|
||||
);
|
||||
if( current_minimum_distance < min_dist ) {
|
||||
//found a new minimum
|
||||
min_dist = current_minimum_distance;
|
||||
result_coordinate.lat = current_edge.lat1;
|
||||
result_coordinate.lon = current_edge.lon1;
|
||||
result_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
|
||||
result_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
|
||||
found_a_nearest_edge = true;
|
||||
}
|
||||
|
||||
current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
current_edge.lat2,
|
||||
current_edge.lon2
|
||||
m_coordinate_list->at(current_edge.v).lat,
|
||||
m_coordinate_list->at(current_edge.v).lon
|
||||
);
|
||||
|
||||
if( current_minimum_distance < min_dist ) {
|
||||
//found a new minimum
|
||||
min_dist = current_minimum_distance;
|
||||
result_coordinate.lat = current_edge.lat2;
|
||||
result_coordinate.lon = current_edge.lon2;
|
||||
result_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
|
||||
result_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
|
||||
found_a_nearest_edge = true;
|
||||
}
|
||||
}
|
||||
@@ -783,7 +672,9 @@ public:
|
||||
}
|
||||
|
||||
double current_ratio = 0.;
|
||||
double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
|
||||
const double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate,
|
||||
nearest,
|
||||
current_ratio
|
||||
@@ -799,41 +690,24 @@ public:
|
||||
)
|
||||
) { //found a new minimum
|
||||
min_dist = current_perpendicular_distance;
|
||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||
result_phantom_node.weight1 = current_edge.weight;
|
||||
result_phantom_node.weight2 = INT_MAX;
|
||||
//TODO: use assignment c'tor in PhantomNode
|
||||
result_phantom_node.forward_node_id = current_edge.forward_edge_based_node_id;
|
||||
result_phantom_node.reverse_node_id = current_edge.reverse_edge_based_node_id;
|
||||
result_phantom_node.name_id = current_edge.name_id;
|
||||
result_phantom_node.forward_weight = current_edge.forward_weight;
|
||||
result_phantom_node.reverse_weight = current_edge.reverse_weight;
|
||||
result_phantom_node.forward_offset = current_edge.forward_offset;
|
||||
result_phantom_node.reverse_offset = current_edge.reverse_offset;
|
||||
result_phantom_node.packed_geometry_id = current_edge.packed_geometry_id;
|
||||
result_phantom_node.fwd_segment_position = current_edge.fwd_segment_position;
|
||||
|
||||
result_phantom_node.location = nearest;
|
||||
current_start_coordinate.lat = current_edge.lat1;
|
||||
current_start_coordinate.lon = current_edge.lon1;
|
||||
current_end_coordinate.lat = current_edge.lat2;
|
||||
current_end_coordinate.lon = current_edge.lon2;
|
||||
current_start_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
|
||||
current_start_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
|
||||
current_end_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
|
||||
current_end_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
|
||||
nearest_edge = current_edge;
|
||||
found_a_nearest_edge = true;
|
||||
} else
|
||||
if( DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||
( 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) ) &&
|
||||
EdgesAreEquivalent(
|
||||
current_start_coordinate,
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat1,
|
||||
current_edge.lon1
|
||||
),
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat2,
|
||||
current_edge.lon2
|
||||
),
|
||||
current_end_coordinate
|
||||
)
|
||||
) {
|
||||
|
||||
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
|
||||
result_phantom_node.weight2 = current_edge.weight;
|
||||
if(current_edge.id < result_phantom_node.edgeBasedNode) {
|
||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
|
||||
std::swap(current_end_coordinate, current_start_coordinate);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -884,11 +758,28 @@ public:
|
||||
ratio = std::min(1., ratio);
|
||||
}
|
||||
|
||||
result_phantom_node.weight1 *= ratio;
|
||||
if(INT_MAX != result_phantom_node.weight2) {
|
||||
result_phantom_node.weight2 *= (1.-ratio);
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_offset: " << result_phantom_node.forward_offset;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_offset: " << result_phantom_node.reverse_offset;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_weight: " << result_phantom_node.forward_weight;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_weight: " << result_phantom_node.reverse_weight;
|
||||
|
||||
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
|
||||
{
|
||||
result_phantom_node.forward_weight *= ratio;
|
||||
}
|
||||
result_phantom_node.ratio = ratio;
|
||||
if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
|
||||
{
|
||||
result_phantom_node.reverse_weight *= (1.-ratio);
|
||||
}
|
||||
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result location: " << result_phantom_node.location << ", start: " << current_start_coordinate << ", end: " << current_end_coordinate;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd node: " << result_phantom_node.forward_node_id << ", rev node: " << result_phantom_node.reverse_node_id;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd weight: " << result_phantom_node.forward_weight << ", rev weight: " << result_phantom_node.reverse_weight;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd offset: " << result_phantom_node.forward_offset << ", rev offset: " << result_phantom_node.reverse_offset;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] bidirected: " << (result_phantom_node.isBidirected() ? "y" : "n");
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] name id: " << result_phantom_node.name_id;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] geom id: " << result_phantom_node.packed_geometry_id;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] ratio: " << ratio;
|
||||
|
||||
return found_a_nearest_edge;
|
||||
}
|
||||
|
||||
@@ -92,6 +92,4 @@ struct TurnInstructionsClass : boost::noncopyable {
|
||||
|
||||
};
|
||||
|
||||
static TurnInstructionsClass TurnInstructions;
|
||||
|
||||
#endif /* TURNINSTRUCTIONS_H_ */
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
|
||||
explicit XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
|
||||
|
||||
inline HashCell& operator[]( const NodeID node ) {
|
||||
unsigned short position = fastHash(node);
|
||||
|
||||
@@ -31,18 +31,18 @@ DescriptionFactory::DescriptionFactory() : entireLength(0) { }
|
||||
|
||||
DescriptionFactory::~DescriptionFactory() { }
|
||||
|
||||
inline double DescriptionFactory::DegreeToRadian(const double degree) const {
|
||||
return degree * (M_PI/180);
|
||||
inline double DescriptionFactory::DegreeToRadian(const double degree) const
|
||||
{
|
||||
return degree * (M_PI/180.);
|
||||
}
|
||||
|
||||
inline double DescriptionFactory::RadianToDegree(const double radian) const {
|
||||
return radian * (180/M_PI);
|
||||
inline double DescriptionFactory::RadianToDegree(const double radian) const
|
||||
{
|
||||
return radian * (180./M_PI);
|
||||
}
|
||||
|
||||
double DescriptionFactory::GetBearing(
|
||||
const FixedPointCoordinate & A,
|
||||
const FixedPointCoordinate & B
|
||||
) const {
|
||||
double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const FixedPointCoordinate & B) const
|
||||
{
|
||||
double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
||||
|
||||
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
||||
@@ -51,55 +51,52 @@ double DescriptionFactory::GetBearing(
|
||||
const double y = sin(delta_long) * cos(lat2);
|
||||
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
|
||||
double result = RadianToDegree(atan2(y, x));
|
||||
while(result < 0.) {
|
||||
while (result < 0.)
|
||||
{
|
||||
result += 360.;
|
||||
}
|
||||
while(result >= 360.) {
|
||||
|
||||
while (result >= 360.)
|
||||
{
|
||||
result -= 360.;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DescriptionFactory::SetStartSegment(const PhantomNode & start) {
|
||||
start_phantom = start;
|
||||
void DescriptionFactory::SetStartSegment(const PhantomNode & source, const bool source_traversed_in_reverse)
|
||||
{
|
||||
start_phantom = source;
|
||||
AppendSegment(
|
||||
start.location,
|
||||
PathData(0, start.nodeBasedEdgeNameID, 10, start.weight1)
|
||||
source.location,
|
||||
PathData(0, source.name_id, 10, source.forward_weight)
|
||||
);
|
||||
}
|
||||
|
||||
void DescriptionFactory::SetEndSegment(const PhantomNode & target) {
|
||||
void DescriptionFactory::SetEndSegment(const PhantomNode & target, const bool target_traversed_in_reverse)
|
||||
{
|
||||
target_phantom = target;
|
||||
pathDescription.push_back(
|
||||
SegmentInformation(
|
||||
target.location,
|
||||
target.nodeBasedEdgeNameID,
|
||||
target.name_id,
|
||||
0,
|
||||
target.weight1,
|
||||
target.reverse_weight,
|
||||
0,
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void DescriptionFactory::AppendSegment(
|
||||
const FixedPointCoordinate & coordinate,
|
||||
const PathData & data
|
||||
) {
|
||||
if(
|
||||
( 1 == pathDescription.size()) &&
|
||||
( pathDescription.back().location == coordinate)
|
||||
) {
|
||||
pathDescription.back().name_id = data.name_id;
|
||||
} else {
|
||||
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const PathData & path_point)
|
||||
{
|
||||
if ((1 == pathDescription.size()) && ( pathDescription.back().location == coordinate))
|
||||
{
|
||||
pathDescription.back().name_id = path_point.name_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
pathDescription.push_back(
|
||||
SegmentInformation(
|
||||
coordinate,
|
||||
data.name_id,
|
||||
data.durationOfSegment,
|
||||
0,
|
||||
data.turnInstruction
|
||||
)
|
||||
SegmentInformation(coordinate, path_point.name_id, path_point.durationOfSegment, 0, path_point.turnInstruction)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -137,7 +134,7 @@ void DescriptionFactory::BuildRouteSummary(
|
||||
const double distance,
|
||||
const unsigned time
|
||||
) {
|
||||
summary.startName = start_phantom.nodeBasedEdgeNameID;
|
||||
summary.destName = target_phantom.nodeBasedEdgeNameID;
|
||||
summary.startName = start_phantom.name_id;
|
||||
summary.destName = target_phantom.name_id;
|
||||
summary.BuildDurationAndLengthStrings(distance, time);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
) {
|
||||
//compute distance/duration for route summary
|
||||
intToString(round(distance), lengthString);
|
||||
int travel_time = time/10;
|
||||
int travel_time = round(time/10.);
|
||||
intToString(std::max(travel_time, 1), durationString);
|
||||
}
|
||||
} summary;
|
||||
@@ -87,8 +87,8 @@ public:
|
||||
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
||||
void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data);
|
||||
void BuildRouteSummary(const double distance, const unsigned time);
|
||||
void SetStartSegment(const PhantomNode & start_phantom);
|
||||
void SetEndSegment(const PhantomNode & start_phantom);
|
||||
void SetStartSegment(const PhantomNode & start_phantom, const bool source_traversed_in_reverse);
|
||||
void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse);
|
||||
void AppendEncodedPolylineString(
|
||||
const bool return_encoded,
|
||||
std::vector<std::string> & output
|
||||
@@ -105,14 +105,13 @@ public:
|
||||
|
||||
/** starts at index 1 */
|
||||
pathDescription[0].length = 0;
|
||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
for (unsigned i = 1; i < pathDescription.size(); ++i)
|
||||
{
|
||||
//move down names by one, q&d hack
|
||||
pathDescription[i-1].name_id = pathDescription[i].name_id;
|
||||
pathDescription[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||
}
|
||||
|
||||
// std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].name_id);
|
||||
// std::string string1;
|
||||
|
||||
|
||||
/*Simplify turn instructions
|
||||
Input :
|
||||
10. Turn left on B 36 for 20 km
|
||||
@@ -154,23 +153,23 @@ public:
|
||||
// string0 = string1;
|
||||
// }
|
||||
|
||||
double lengthOfSegment = 0;
|
||||
unsigned durationOfSegment = 0;
|
||||
unsigned indexOfSegmentBegin = 0;
|
||||
double segment_length = 0.;
|
||||
unsigned segment_duration = 0;
|
||||
unsigned segment_start_index = 0;
|
||||
|
||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
entireLength += pathDescription[i].length;
|
||||
lengthOfSegment += pathDescription[i].length;
|
||||
durationOfSegment += pathDescription[i].duration;
|
||||
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
||||
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
||||
segment_length += pathDescription[i].length;
|
||||
segment_duration += pathDescription[i].duration;
|
||||
pathDescription[segment_start_index].length = segment_length;
|
||||
pathDescription[segment_start_index].duration = segment_duration;
|
||||
|
||||
|
||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
|
||||
BOOST_ASSERT(pathDescription[i].necessary);
|
||||
lengthOfSegment = 0;
|
||||
durationOfSegment = 0;
|
||||
indexOfSegmentBegin = i;
|
||||
segment_length = 0;
|
||||
segment_duration = 0;
|
||||
segment_start_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,21 +178,17 @@ public:
|
||||
if(pathDescription.size() > 2){
|
||||
pathDescription.pop_back();
|
||||
pathDescription.back().necessary = true;
|
||||
pathDescription.back().turn_instruction = TurnInstructions.NoTurn;
|
||||
target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->name_id;
|
||||
pathDescription.back().turn_instruction = TurnInstructionsClass::NoTurn;
|
||||
target_phantom.name_id = (pathDescription.end()-2)->name_id;
|
||||
}
|
||||
} else {
|
||||
pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
|
||||
}
|
||||
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
|
||||
if(pathDescription.size() > 2) {
|
||||
pathDescription.erase(pathDescription.begin());
|
||||
pathDescription[0].turn_instruction = TurnInstructions.HeadOn;
|
||||
pathDescription[0].turn_instruction = TurnInstructionsClass::HeadOn;
|
||||
pathDescription[0].necessary = true;
|
||||
start_phantom.nodeBasedEdgeNameID = pathDescription[0].name_id;
|
||||
start_phantom.name_id = pathDescription[0].name_id;
|
||||
}
|
||||
} else {
|
||||
pathDescription[0].duration *= start_phantom.ratio;
|
||||
}
|
||||
|
||||
//Generalize poly line
|
||||
|
||||
@@ -65,12 +65,12 @@ public:
|
||||
(raw_route.unpacked_path_segments[0].size());
|
||||
if( found_route ) {
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.startPhantom.location.lat,
|
||||
phantom_node_list.source_phantom.location.lat,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.startPhantom.location.lon,
|
||||
phantom_node_list.source_phantom.location.lon,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||
@@ -90,12 +90,12 @@ public:
|
||||
}
|
||||
// Add the via point or the end coordinate
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.targetPhantom.location.lat,
|
||||
phantom_node_list.target_phantom.location.lat,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.targetPhantom.location.lon,
|
||||
phantom_node_list.target_phantom.location.lon,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||
|
||||
@@ -44,6 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
template<class DataFacadeT>
|
||||
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
|
||||
private:
|
||||
// TODO: initalize in c'tor
|
||||
DataFacadeT * facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory;
|
||||
@@ -59,7 +60,7 @@ private:
|
||||
int start_index;
|
||||
int name_id;
|
||||
int leave_at_exit;
|
||||
} roundAbout;
|
||||
} round_about;
|
||||
|
||||
struct Segment {
|
||||
Segment() : name_id(-1), length(-1), position(-1) {}
|
||||
@@ -90,7 +91,7 @@ public:
|
||||
void SetConfig(const DescriptorConfig & c) { config = c; }
|
||||
|
||||
int DescribeLeg(
|
||||
const std::vector<PathData> & route_leg,
|
||||
const std::vector<PathData> route_leg,
|
||||
const PhantomNodes & leg_phantoms
|
||||
) {
|
||||
int added_element_count = 0;
|
||||
@@ -98,10 +99,10 @@ public:
|
||||
FixedPointCoordinate current_coordinate;
|
||||
BOOST_FOREACH(const PathData & path_data, route_leg) {
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data );
|
||||
description_factory.AppendSegment(current_coordinate, path_data);
|
||||
++added_element_count;
|
||||
}
|
||||
// description_factory.SetEndSegment( leg_phantoms.targetPhantom );
|
||||
// description_factory.SetEndSegment( leg_phantoms.target_phantom );
|
||||
++added_element_count;
|
||||
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count );
|
||||
return added_element_count;
|
||||
@@ -119,7 +120,8 @@ public:
|
||||
"{\"status\":"
|
||||
);
|
||||
|
||||
if(INT_MAX == raw_route.lengthOfShortestPath) {
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath)
|
||||
{
|
||||
//We do not need to do much, if there is no route ;-)
|
||||
reply.content.push_back(
|
||||
"207,\"status_message\": \"Cannot find route between points\"}"
|
||||
@@ -127,12 +129,36 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
description_factory.SetStartSegment(phantom_nodes.startPhantom);
|
||||
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath;
|
||||
|
||||
//check if first segment is non-zero
|
||||
std::string road_name;
|
||||
road_name = facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
|
||||
|
||||
// for each unpacked segment add the leg to the description
|
||||
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
|
||||
|
||||
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
||||
{
|
||||
const std::vector<PathData> & leg_path = raw_route.unpacked_path_segments[i];
|
||||
FixedPointCoordinate current_coordinate;
|
||||
BOOST_FOREACH(const PathData & path_data, leg_path)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
road_name = facade->GetEscapedNameForNameID(path_data.name_id);
|
||||
}
|
||||
}
|
||||
|
||||
//check if last segment is non-zero
|
||||
road_name = facade->GetEscapedNameForNameID(phantom_nodes.target_phantom.name_id);
|
||||
|
||||
description_factory.SetStartSegment(phantom_nodes.source_phantom, raw_route.source_traversed_in_reverse);
|
||||
reply.content.push_back("0,"
|
||||
"\"status_message\": \"Found route between points\",");
|
||||
|
||||
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
|
||||
for( unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i ) {
|
||||
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
||||
{
|
||||
const int added_segments = DescribeLeg(
|
||||
raw_route.unpacked_path_segments[i],
|
||||
raw_route.segmentEndCoordinates[i]
|
||||
@@ -142,7 +168,7 @@ public:
|
||||
added_segments + shortest_leg_end_indices.back()
|
||||
);
|
||||
}
|
||||
description_factory.SetEndSegment(phantom_nodes.targetPhantom);
|
||||
description_factory.SetEndSegment(phantom_nodes.target_phantom, raw_route.target_traversed_in_reverse);
|
||||
description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
reply.content.push_back("\"route_geometry\": ");
|
||||
@@ -194,14 +220,15 @@ public:
|
||||
|
||||
//only one alternative route is computed at this time, so this is hardcoded
|
||||
|
||||
if(raw_route.lengthOfAlternativePath != INT_MAX) {
|
||||
alternate_descriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
|
||||
if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse);
|
||||
//Get all the coordinates for the computed route
|
||||
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) {
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
alternate_descriptionFactory.AppendSegment(current, path_data );
|
||||
}
|
||||
alternate_descriptionFactory.SetEndSegment(phantom_nodes.targetPhantom);
|
||||
alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom, raw_route.alt_target_traversed_in_reverse);
|
||||
}
|
||||
alternate_descriptionFactory.Run(facade, config.zoom_level);
|
||||
|
||||
@@ -286,7 +313,7 @@ public:
|
||||
|
||||
std::string tmp;
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
raw_route.segmentEndCoordinates.front().startPhantom.location,
|
||||
raw_route.segmentEndCoordinates.front().source_phantom.location,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("[");
|
||||
@@ -296,7 +323,7 @@ public:
|
||||
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) {
|
||||
tmp.clear();
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
nodes.targetPhantom.location,
|
||||
nodes.target_phantom.location,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back(",[");
|
||||
@@ -332,11 +359,11 @@ public:
|
||||
std::string hint;
|
||||
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) {
|
||||
reply.content.push_back("\"");
|
||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].startPhantom, hint);
|
||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].source_phantom, hint);
|
||||
reply.content.push_back(hint);
|
||||
reply.content.push_back("\", ");
|
||||
}
|
||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().targetPhantom, hint);
|
||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().target_phantom, hint);
|
||||
reply.content.push_back("\"");
|
||||
reply.content.push_back(hint);
|
||||
reply.content.push_back("\"]");
|
||||
@@ -419,56 +446,61 @@ public:
|
||||
//Segment information has following format:
|
||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
||||
unsigned prefixSumOfNecessarySegments = 0;
|
||||
roundAbout.leave_at_exit = 0;
|
||||
roundAbout.name_id = 0;
|
||||
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
||||
unsigned necessary_segments_running_index = 0;
|
||||
round_about.leave_at_exit = 0;
|
||||
round_about.name_id = 0;
|
||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||
|
||||
//Fetch data from Factory and generate a string from it.
|
||||
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
|
||||
TurnInstruction current_instruction = segment.turn_instruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
TurnInstruction current_instruction = segment.turn_instruction & TurnInstructionsClass::InverseAccessRestrictionFlag;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if(TurnInstructions.TurnIsNecessary( current_instruction) ) {
|
||||
if(TurnInstructions.EnterRoundAbout == current_instruction) {
|
||||
roundAbout.name_id = segment.name_id;
|
||||
roundAbout.start_index = prefixSumOfNecessarySegments;
|
||||
} else {
|
||||
if(0 != prefixSumOfNecessarySegments){
|
||||
if (TurnInstructionsClass::TurnIsNecessary( current_instruction) )
|
||||
{
|
||||
if (TurnInstructionsClass::EnterRoundAbout == current_instruction)
|
||||
{
|
||||
round_about.name_id = segment.name_id;
|
||||
round_about.start_index = necessary_segments_running_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != necessary_segments_running_index)
|
||||
{
|
||||
reply.content.push_back(",");
|
||||
}
|
||||
reply.content.push_back("[\"");
|
||||
if(TurnInstructions.LeaveRoundAbout == current_instruction) {
|
||||
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
|
||||
reply.content.push_back(tmpInstruction);
|
||||
if(TurnInstructionsClass::LeaveRoundAbout == current_instruction) {
|
||||
intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction);
|
||||
reply.content.push_back(temp_instruction);
|
||||
reply.content.push_back("-");
|
||||
intToString(roundAbout.leave_at_exit+1, tmpInstruction);
|
||||
reply.content.push_back(tmpInstruction);
|
||||
roundAbout.leave_at_exit = 0;
|
||||
intToString(round_about.leave_at_exit+1, temp_instruction);
|
||||
reply.content.push_back(temp_instruction);
|
||||
round_about.leave_at_exit = 0;
|
||||
} else {
|
||||
intToString(current_instruction, tmpInstruction);
|
||||
reply.content.push_back(tmpInstruction);
|
||||
intToString(current_instruction, temp_instruction);
|
||||
reply.content.push_back(temp_instruction);
|
||||
}
|
||||
|
||||
reply.content.push_back("\",\"");
|
||||
reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id));
|
||||
reply.content.push_back("\",");
|
||||
intToString(segment.length, tmpDist);
|
||||
reply.content.push_back(tmpDist);
|
||||
intToString(segment.length, temp_dist);
|
||||
reply.content.push_back(temp_dist);
|
||||
reply.content.push_back(",");
|
||||
intToString(prefixSumOfNecessarySegments, tmpLength);
|
||||
reply.content.push_back(tmpLength);
|
||||
intToString(necessary_segments_running_index, temp_length);
|
||||
reply.content.push_back(temp_length);
|
||||
reply.content.push_back(",");
|
||||
intToString(segment.duration/10, tmpDuration);
|
||||
reply.content.push_back(tmpDuration);
|
||||
intToString(round(segment.duration/10.), temp_duration);
|
||||
reply.content.push_back(temp_duration);
|
||||
reply.content.push_back(",\"");
|
||||
intToString(segment.length, tmpLength);
|
||||
reply.content.push_back(tmpLength);
|
||||
intToString(segment.length, temp_length);
|
||||
reply.content.push_back(temp_length);
|
||||
reply.content.push_back("m\",\"");
|
||||
double bearing_value = round(segment.bearing/10.);
|
||||
reply.content.push_back(Azimuth::Get(bearing_value));
|
||||
reply.content.push_back("\",");
|
||||
intToString(bearing_value, tmpBearing);
|
||||
reply.content.push_back(tmpBearing);
|
||||
intToString(bearing_value, temp_bearing);
|
||||
reply.content.push_back(temp_bearing);
|
||||
reply.content.push_back("]");
|
||||
|
||||
route_segments_list.push_back(
|
||||
@@ -479,22 +511,22 @@ public:
|
||||
)
|
||||
);
|
||||
}
|
||||
} else if(TurnInstructions.StayOnRoundAbout == current_instruction) {
|
||||
++roundAbout.leave_at_exit;
|
||||
} else if(TurnInstructionsClass::StayOnRoundAbout == current_instruction) {
|
||||
++round_about.leave_at_exit;
|
||||
}
|
||||
if(segment.necessary)
|
||||
++prefixSumOfNecessarySegments;
|
||||
++necessary_segments_running_index;
|
||||
}
|
||||
if(INT_MAX != route_length) {
|
||||
reply.content.push_back(",[\"");
|
||||
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
|
||||
reply.content.push_back(tmpInstruction);
|
||||
intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction);
|
||||
reply.content.push_back(temp_instruction);
|
||||
reply.content.push_back("\",\"");
|
||||
reply.content.push_back("\",");
|
||||
reply.content.push_back("0");
|
||||
reply.content.push_back(",");
|
||||
intToString(prefixSumOfNecessarySegments-1, tmpLength);
|
||||
reply.content.push_back(tmpLength);
|
||||
intToString(necessary_segments_running_index-1, temp_length);
|
||||
reply.content.push_back(temp_length);
|
||||
reply.content.push_back(",");
|
||||
reply.content.push_back("0");
|
||||
reply.content.push_back(",\"");
|
||||
|
||||
@@ -362,7 +362,6 @@ void ExtractionContainers::PrepareData(
|
||||
break;
|
||||
default:
|
||||
throw OSRMException("edge has broken direction");
|
||||
break;
|
||||
}
|
||||
file_out_stream.write(
|
||||
(char*)&integer_weight, sizeof(int)
|
||||
@@ -373,23 +372,27 @@ void ExtractionContainers::PrepareData(
|
||||
sizeof(short)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char*)&edge_iterator->nameID,
|
||||
(char *) &edge_iterator->nameID,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char*)&edge_iterator->isRoundabout,
|
||||
(char *) &edge_iterator->isRoundabout,
|
||||
sizeof(bool)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char*)&edge_iterator->ignoreInGrid,
|
||||
(char *) &edge_iterator->ignoreInGrid,
|
||||
sizeof(bool)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char*)&edge_iterator->isAccessRestricted,
|
||||
(char *) &edge_iterator->isAccessRestricted,
|
||||
sizeof(bool)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char*)&edge_iterator->isContraFlow,
|
||||
(char *) &edge_iterator->isContraFlow,
|
||||
sizeof(bool)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char *) &edge_iterator->is_split,
|
||||
sizeof(bool)
|
||||
);
|
||||
++number_of_used_edges;
|
||||
|
||||
@@ -75,13 +75,13 @@ inline unsigned parseDuration(const std::string &s) {
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
|
||||
boost::algorithm::to_lower(input);
|
||||
int n = stringToInt(input);
|
||||
if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
|
||||
n = (n*1609)/1000;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
// inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
|
||||
// boost::algorithm::to_lower(input);
|
||||
// int n = stringToInt(input);
|
||||
// if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
|
||||
// n = (n*1609)/1000;
|
||||
// }
|
||||
// return n;
|
||||
// }
|
||||
|
||||
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
|
||||
|
||||
@@ -25,36 +25,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionHelperFunctions.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionWay.h"
|
||||
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks()
|
||||
:
|
||||
stringMap(NULL),
|
||||
string_map(NULL),
|
||||
externalMemory(NULL)
|
||||
{ }
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks(
|
||||
ExtractionContainers * ext,
|
||||
StringMap * strMap
|
||||
boost::unordered_map<std::string, NodeID> * string_map
|
||||
) :
|
||||
stringMap(strMap),
|
||||
string_map(string_map),
|
||||
externalMemory(ext)
|
||||
{ }
|
||||
|
||||
@@ -94,11 +88,11 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
||||
}
|
||||
|
||||
//Get the unique identifier for the street name
|
||||
const StringMap::const_iterator & string_map_iterator = stringMap->find(parsed_way.name);
|
||||
if(stringMap->end() == string_map_iterator) {
|
||||
const boost::unordered_map<std::string, NodeID>::const_iterator & string_map_iterator = string_map->find(parsed_way.name);
|
||||
if(string_map->end() == string_map_iterator) {
|
||||
parsed_way.nameID = externalMemory->name_list.size();
|
||||
externalMemory->name_list.push_back(parsed_way.name);
|
||||
stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||
string_map->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||
} else {
|
||||
parsed_way.nameID = string_map_iterator->second;
|
||||
}
|
||||
@@ -112,16 +106,19 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
||||
|
||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||
externalMemory->all_edges_list.push_back(
|
||||
InternalExtractorEdge(parsed_way.path[n],
|
||||
parsed_way.path[n+1],
|
||||
parsed_way.type,
|
||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||
parsed_way.speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted
|
||||
InternalExtractorEdge(
|
||||
parsed_way.path[n],
|
||||
parsed_way.path[n+1],
|
||||
parsed_way.type,
|
||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||
parsed_way.speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
false,
|
||||
split_bidirectional_edge
|
||||
)
|
||||
);
|
||||
externalMemory->used_node_id_list.push_back(parsed_way.path[n]);
|
||||
@@ -135,17 +132,19 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
||||
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
|
||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||
externalMemory->all_edges_list.push_back(
|
||||
InternalExtractorEdge(parsed_way.path[n],
|
||||
parsed_way.path[n+1],
|
||||
parsed_way.type,
|
||||
ExtractionWay::oneway,
|
||||
parsed_way.backward_speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
(ExtractionWay::oneway == parsed_way.direction)
|
||||
InternalExtractorEdge(
|
||||
parsed_way.path[n],
|
||||
parsed_way.path[n+1],
|
||||
parsed_way.type,
|
||||
ExtractionWay::oneway,
|
||||
parsed_way.backward_speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
(ExtractionWay::oneway == parsed_way.direction),
|
||||
split_bidirectional_edge
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -28,29 +28,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTORCALLBACKS_H_
|
||||
#define EXTRACTORCALLBACKS_H_
|
||||
|
||||
#include "ExtractorStructs.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <string>
|
||||
|
||||
struct ExternalMemoryNode;
|
||||
class ExtractionContainers;
|
||||
struct ExtractionWay;
|
||||
struct InputRestrictionContainer;
|
||||
|
||||
typedef boost::unordered_map<std::string, NodeID> StringMap;
|
||||
|
||||
class ExtractorCallbacks{
|
||||
private:
|
||||
|
||||
StringMap * stringMap;
|
||||
boost::unordered_map<std::string, NodeID> * string_map;
|
||||
ExtractionContainers * externalMemory;
|
||||
|
||||
ExtractorCallbacks();
|
||||
public:
|
||||
explicit ExtractorCallbacks(
|
||||
ExtractionContainers * ext,
|
||||
StringMap * strMap
|
||||
boost::unordered_map<std::string, NodeID> * string_map
|
||||
);
|
||||
|
||||
~ExtractorCallbacks();
|
||||
|
||||
@@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef INTERNAL_EXTRACTOR_EDGE_H
|
||||
#define INTERNAL_EXTRACTOR_EDGE_H
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
@@ -47,70 +47,10 @@ struct InternalExtractorEdge {
|
||||
ignoreInGrid(false),
|
||||
isDurationSet(false),
|
||||
isAccessRestricted(false),
|
||||
isContraFlow(false)
|
||||
isContraFlow(false),
|
||||
is_split(false)
|
||||
{ }
|
||||
|
||||
explicit InternalExtractorEdge(NodeID start, NodeID target)
|
||||
:
|
||||
start(start),
|
||||
target(target),
|
||||
type(0),
|
||||
direction(0),
|
||||
speed(0),
|
||||
nameID(0),
|
||||
isRoundabout(false),
|
||||
ignoreInGrid(false),
|
||||
isDurationSet(false),
|
||||
isAccessRestricted(false),
|
||||
isContraFlow(false)
|
||||
{ }
|
||||
|
||||
explicit InternalExtractorEdge(
|
||||
NodeID start,
|
||||
NodeID target,
|
||||
short type,
|
||||
short d,
|
||||
double speed
|
||||
) :
|
||||
start(start),
|
||||
target(target),
|
||||
type(type),
|
||||
direction(d),
|
||||
speed(speed),
|
||||
nameID(0),
|
||||
isRoundabout(false),
|
||||
ignoreInGrid(false),
|
||||
isDurationSet(false),
|
||||
isAccessRestricted(false),
|
||||
isContraFlow(false)
|
||||
{ }
|
||||
|
||||
explicit InternalExtractorEdge(
|
||||
NodeID start,
|
||||
NodeID target,
|
||||
short type,
|
||||
short direction,
|
||||
double speed,
|
||||
unsigned nameID,
|
||||
bool isRoundabout,
|
||||
bool ignoreInGrid,
|
||||
bool isDurationSet,
|
||||
bool isAccressRestricted
|
||||
) :
|
||||
start(start),
|
||||
target(target),
|
||||
type(type),
|
||||
direction(direction),
|
||||
speed(speed),
|
||||
nameID(nameID),
|
||||
isRoundabout(isRoundabout),
|
||||
ignoreInGrid(ignoreInGrid),
|
||||
isDurationSet(isDurationSet),
|
||||
isAccessRestricted(isAccressRestricted),
|
||||
isContraFlow(false)
|
||||
{
|
||||
BOOST_ASSERT(0 <= type);
|
||||
}
|
||||
|
||||
explicit InternalExtractorEdge(
|
||||
NodeID start,
|
||||
@@ -123,7 +63,8 @@ struct InternalExtractorEdge {
|
||||
bool ignoreInGrid,
|
||||
bool isDurationSet,
|
||||
bool isAccressRestricted,
|
||||
bool isContraFlow
|
||||
bool isContraFlow,
|
||||
bool is_split
|
||||
) :
|
||||
start(start),
|
||||
target(target),
|
||||
@@ -135,19 +76,43 @@ struct InternalExtractorEdge {
|
||||
ignoreInGrid(ignoreInGrid),
|
||||
isDurationSet(isDurationSet),
|
||||
isAccessRestricted(isAccressRestricted),
|
||||
isContraFlow(isContraFlow)
|
||||
isContraFlow(isContraFlow),
|
||||
is_split(is_split)
|
||||
{
|
||||
BOOST_ASSERT(0 <= type);
|
||||
}
|
||||
|
||||
// necessary static util functions for stxxl's sorting
|
||||
static InternalExtractorEdge min_value() {
|
||||
return InternalExtractorEdge(0,0);
|
||||
return InternalExtractorEdge(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
static InternalExtractorEdge max_value() {
|
||||
return InternalExtractorEdge(
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max()
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@@ -162,6 +127,7 @@ struct InternalExtractorEdge {
|
||||
bool isDurationSet;
|
||||
bool isAccessRestricted;
|
||||
bool isContraFlow;
|
||||
bool is_split;
|
||||
|
||||
FixedPointCoordinate startCoord;
|
||||
FixedPointCoordinate targetCoord;
|
||||
|
||||
+24
-22
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/MachineInfo.h"
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
@@ -214,25 +215,26 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
||||
denseTagIndex += 2;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma omp parallel
|
||||
{
|
||||
const int thread_num = omp_get_thread_num();
|
||||
#pragma omp parallel for schedule ( guided )
|
||||
for(int i = 0; i < number_of_nodes; ++i) {
|
||||
for(int i = 0; i < number_of_nodes; ++i)
|
||||
{
|
||||
ImportNode & import_node = extracted_nodes_vector[i];
|
||||
ParseNodeInLua(
|
||||
import_node,
|
||||
scripting_environment.getLuaStateForThreadID(omp_get_thread_num())
|
||||
);
|
||||
ParseNodeInLua(import_node, scripting_environment.getLuaStateForThreadID(thread_num));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const ImportNode &import_node, extracted_nodes_vector) {
|
||||
BOOST_FOREACH(const ImportNode &import_node, extracted_nodes_vector)
|
||||
{
|
||||
extractor_callbacks->nodeFunction(import_node);
|
||||
}
|
||||
}
|
||||
|
||||
inline void PBFParser::parseNode(_ThreadData * ) {
|
||||
throw OSRMException(
|
||||
"Parsing of simple nodes not supported. PBF should use dense nodes"
|
||||
);
|
||||
inline void PBFParser::parseNode(_ThreadData * )
|
||||
{
|
||||
throw OSRMException("Parsing of simple nodes not supported. PBF should use dense nodes");
|
||||
}
|
||||
|
||||
inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||
@@ -351,24 +353,24 @@ inline void PBFParser::parseWay(_ThreadData * threadData) {
|
||||
}
|
||||
|
||||
#pragma omp parallel for schedule ( guided )
|
||||
for(int i = 0; i < number_of_ways; ++i) {
|
||||
for(int i = 0; i < number_of_ways; ++i)
|
||||
{
|
||||
ExtractionWay & extraction_way = parsed_way_vector[i];
|
||||
if (2 > extraction_way.path.size())
|
||||
if (2 <= extraction_way.path.size())
|
||||
{
|
||||
continue;
|
||||
ParseWayInLua(
|
||||
extraction_way,
|
||||
scripting_environment.getLuaStateForThreadID(omp_get_thread_num())
|
||||
);
|
||||
}
|
||||
ParseWayInLua(
|
||||
extraction_way,
|
||||
scripting_environment.getLuaStateForThreadID( omp_get_thread_num())
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(ExtractionWay & extraction_way, parsed_way_vector) {
|
||||
if (2 > extraction_way.path.size())
|
||||
BOOST_FOREACH(ExtractionWay & extraction_way, parsed_way_vector)
|
||||
{
|
||||
if (2 <= extraction_way.path.size())
|
||||
{
|
||||
continue;
|
||||
extractor_callbacks->wayFunction(extraction_way);
|
||||
}
|
||||
extractor_callbacks->wayFunction(extraction_way);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,13 +76,13 @@ public:
|
||||
private:
|
||||
inline void ReadData();
|
||||
inline void ParseData();
|
||||
inline void parseDenseNode (_ThreadData * threadData);
|
||||
inline void parseNode (_ThreadData * threadData);
|
||||
inline void parseRelation (_ThreadData * threadData);
|
||||
inline void parseWay (_ThreadData * threadData);
|
||||
inline void parseDenseNode (_ThreadData * threadData);
|
||||
inline void parseNode (_ThreadData * threadData);
|
||||
inline void parseRelation (_ThreadData * threadData);
|
||||
inline void parseWay (_ThreadData * threadData);
|
||||
|
||||
inline void loadGroup (_ThreadData * threadData);
|
||||
inline void loadBlock (_ThreadData * threadData);
|
||||
inline void loadGroup (_ThreadData * threadData);
|
||||
inline void loadBlock (_ThreadData * threadData);
|
||||
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
|
||||
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData);
|
||||
inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData);
|
||||
|
||||
@@ -58,7 +58,6 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||
// Add our function to the state's global scope
|
||||
luabind::module(myLuaState) [
|
||||
luabind::def("print", LUA_print<std::string>),
|
||||
luabind::def("parseMaxspeed", parseMaxspeed),
|
||||
luabind::def("durationIsValid", durationIsValid),
|
||||
luabind::def("parseDuration", parseDuration)
|
||||
];
|
||||
@@ -106,9 +105,8 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||
|
||||
// fails on c++11/OS X 10.9
|
||||
luabind::module(myLuaState) [
|
||||
luabind::class_<std::vector<std::string> >("vector")
|
||||
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back)
|
||||
)
|
||||
luabind::class_<std::vector<std::string> >("vector")
|
||||
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back))
|
||||
];
|
||||
|
||||
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
||||
|
||||
@@ -35,7 +35,7 @@ struct lua_State;
|
||||
class ScriptingEnvironment {
|
||||
public:
|
||||
ScriptingEnvironment();
|
||||
ScriptingEnvironment(const char * fileName);
|
||||
explicit ScriptingEnvironment(const char * fileName);
|
||||
virtual ~ScriptingEnvironment();
|
||||
|
||||
lua_State * getLuaStateForThreadID(const int);
|
||||
|
||||
+278
-218
@@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "XMLParser.h"
|
||||
|
||||
#include "ExtractionWay.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../DataStructures/InputReaderFactory.h"
|
||||
@@ -40,249 +42,307 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
|
||||
inputReader = inputReaderFactory(filename);
|
||||
XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se)
|
||||
: BaseParser(ec, se)
|
||||
{
|
||||
inputReader = inputReaderFactory(filename);
|
||||
}
|
||||
|
||||
bool XMLParser::ReadHeader() {
|
||||
return (xmlTextReaderRead( inputReader ) == 1);
|
||||
}
|
||||
bool XMLParser::Parse() {
|
||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int type = xmlTextReaderNodeType( inputReader );
|
||||
bool XMLParser::ReadHeader() { return (xmlTextReaderRead(inputReader) == 1); }
|
||||
bool XMLParser::Parse()
|
||||
{
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int type = xmlTextReaderNodeType(inputReader);
|
||||
|
||||
//1 is Element
|
||||
if ( type != 1 ) {
|
||||
continue;
|
||||
}
|
||||
// 1 is Element
|
||||
if (type != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
xmlChar* currentName = xmlTextReaderName( inputReader );
|
||||
if ( currentName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
xmlChar *currentName = xmlTextReaderName(inputReader);
|
||||
if (currentName == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
|
||||
ImportNode n = _ReadXMLNode();
|
||||
ParseNodeInLua( n, lua_state );
|
||||
extractor_callbacks->nodeFunction(n);
|
||||
// if(!extractor_callbacks->nodeFunction(n))
|
||||
// std::cerr << "[XMLParser] dense node not parsed" << std::endl;
|
||||
}
|
||||
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
|
||||
{
|
||||
ImportNode n = ReadXMLNode();
|
||||
ParseNodeInLua(n, lua_state);
|
||||
extractor_callbacks->nodeFunction(n);
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||
ExtractionWay way = _ReadXMLWay( );
|
||||
ParseWayInLua( way, lua_state );
|
||||
extractor_callbacks->wayFunction(way);
|
||||
// if(!extractor_callbacks->wayFunction(way))
|
||||
// std::cerr << "[PBFParser] way not parsed" << std::endl;
|
||||
}
|
||||
if( use_turn_restrictions ) {
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||
InputRestrictionContainer r = _ReadXMLRestriction();
|
||||
if(r.fromWay != UINT_MAX) {
|
||||
if(!extractor_callbacks->restrictionFunction(r)) {
|
||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlFree( currentName );
|
||||
}
|
||||
return true;
|
||||
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
|
||||
{
|
||||
ExtractionWay way = ReadXMLWay();
|
||||
ParseWayInLua(way, lua_state);
|
||||
extractor_callbacks->wayFunction(way);
|
||||
}
|
||||
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
|
||||
{
|
||||
InputRestrictionContainer r = ReadXMLRestriction();
|
||||
if ((UINT_MAX != r.fromWay) && !extractor_callbacks->restrictionFunction(r))
|
||||
{
|
||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||
}
|
||||
}
|
||||
xmlFree(currentName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
InputRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
||||
InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
||||
{
|
||||
InputRestrictionContainer restriction;
|
||||
std::string except_tag_string;
|
||||
|
||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int childType = xmlTextReaderNodeType( inputReader );
|
||||
if ( childType != 1 && childType != 15 ) {
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||
if ( childName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||
xmlFree( childName );
|
||||
break;
|
||||
}
|
||||
if ( childType != 1 ) {
|
||||
xmlFree( childName );
|
||||
continue;
|
||||
}
|
||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
||||
{
|
||||
const int depth = xmlTextReaderDepth(inputReader);
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int childType = xmlTextReaderNodeType(inputReader);
|
||||
if (childType != 1 && childType != 15)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
||||
if (childName == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (depth == childDepth && childType == 15 &&
|
||||
xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
break;
|
||||
}
|
||||
if (childType != 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||
if ( k != NULL && value != NULL ) {
|
||||
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
|
||||
if(0 == std::string((const char *) value).find("only_")) {
|
||||
restriction.restriction.flags.isOnly = true;
|
||||
}
|
||||
}
|
||||
if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
|
||||
except_tag_string = (const char*) value;
|
||||
}
|
||||
}
|
||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
||||
{
|
||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||
if (k != NULL && value != NULL)
|
||||
{
|
||||
if (xmlStrEqual(k, (const xmlChar *)"restriction") &&
|
||||
(0 == std::string((const char *)value).find("only_")))
|
||||
{
|
||||
restriction.restriction.flags.isOnly = true;
|
||||
}
|
||||
if (xmlStrEqual(k, (const xmlChar *)"except"))
|
||||
{
|
||||
except_tag_string = (const char *)value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( k != NULL ) {
|
||||
xmlFree( k );
|
||||
}
|
||||
if ( value != NULL ) {
|
||||
xmlFree( value );
|
||||
}
|
||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
|
||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
||||
if ( ref != NULL ) {
|
||||
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
|
||||
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
|
||||
if (k != NULL)
|
||||
{
|
||||
xmlFree(k);
|
||||
}
|
||||
if (value != NULL)
|
||||
{
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
else if (xmlStrEqual(childName, (const xmlChar *)"member") == 1)
|
||||
{
|
||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||
if (ref != NULL)
|
||||
{
|
||||
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
|
||||
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
|
||||
|
||||
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
||||
restriction.toWay = stringToUint((const char*) ref);
|
||||
}
|
||||
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
||||
restriction.fromWay = stringToUint((const char*) ref);
|
||||
}
|
||||
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
|
||||
restriction.restriction.viaNode = stringToUint((const char*) ref);
|
||||
}
|
||||
if (xmlStrEqual(role, (const xmlChar *)"to") &&
|
||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||
{
|
||||
restriction.toWay = stringToUint((const char *)ref);
|
||||
}
|
||||
if (xmlStrEqual(role, (const xmlChar *)"from") &&
|
||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||
{
|
||||
restriction.fromWay = stringToUint((const char *)ref);
|
||||
}
|
||||
if (xmlStrEqual(role, (const xmlChar *)"via") &&
|
||||
xmlStrEqual(type, (const xmlChar *)"node"))
|
||||
{
|
||||
restriction.restriction.viaNode = stringToUint((const char *)ref);
|
||||
}
|
||||
|
||||
if(NULL != type) {
|
||||
xmlFree( type );
|
||||
}
|
||||
if(NULL != role) {
|
||||
xmlFree( role );
|
||||
}
|
||||
if(NULL != ref) {
|
||||
xmlFree( ref );
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlFree( childName );
|
||||
}
|
||||
}
|
||||
if (NULL != type)
|
||||
{
|
||||
xmlFree(type);
|
||||
}
|
||||
if (NULL != role)
|
||||
{
|
||||
xmlFree(role);
|
||||
}
|
||||
if (NULL != ref)
|
||||
{
|
||||
xmlFree(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlFree(childName);
|
||||
}
|
||||
}
|
||||
|
||||
if( ShouldIgnoreRestriction(except_tag_string) ) {
|
||||
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
|
||||
}
|
||||
return restriction;
|
||||
if (ShouldIgnoreRestriction(except_tag_string))
|
||||
{
|
||||
restriction.fromWay = UINT_MAX; // workaround to ignore the restriction
|
||||
}
|
||||
return restriction;
|
||||
}
|
||||
|
||||
ExtractionWay XMLParser::_ReadXMLWay() {
|
||||
ExtractionWay way;
|
||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||
const int depth = xmlTextReaderDepth( inputReader );
|
||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int childType = xmlTextReaderNodeType( inputReader );
|
||||
if ( childType != 1 && childType != 15 ) {
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||
if ( childName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
ExtractionWay XMLParser::ReadXMLWay()
|
||||
{
|
||||
ExtractionWay way;
|
||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
||||
{
|
||||
const int depth = xmlTextReaderDepth(inputReader);
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int childType = xmlTextReaderNodeType(inputReader);
|
||||
if (childType != 1 && childType != 15)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
||||
if (childName == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
||||
way.id = stringToUint((char*)id);
|
||||
xmlFree(id);
|
||||
xmlFree( childName );
|
||||
break;
|
||||
}
|
||||
if ( childType != 1 ) {
|
||||
xmlFree( childName );
|
||||
continue;
|
||||
}
|
||||
if (depth == childDepth && childType == 15 &&
|
||||
xmlStrEqual(childName, (const xmlChar *)"way") == 1)
|
||||
{
|
||||
xmlChar *id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||
way.id = stringToUint((char *)id);
|
||||
xmlFree(id);
|
||||
xmlFree(childName);
|
||||
break;
|
||||
}
|
||||
if (childType != 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||
// cout << "->k=" << k << ", v=" << value << endl;
|
||||
if ( k != NULL && value != NULL ) {
|
||||
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value));
|
||||
}
|
||||
if ( k != NULL ) {
|
||||
xmlFree( k );
|
||||
}
|
||||
if ( value != NULL ) {
|
||||
xmlFree( value );
|
||||
}
|
||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
|
||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
||||
if ( ref != NULL ) {
|
||||
way.path.push_back( stringToUint(( const char* ) ref ) );
|
||||
xmlFree( ref );
|
||||
}
|
||||
}
|
||||
xmlFree( childName );
|
||||
}
|
||||
}
|
||||
return way;
|
||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
||||
{
|
||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||
|
||||
if (k != NULL && value != NULL)
|
||||
{
|
||||
way.keyVals.Add(std::string((char *)k), std::string((char *)value));
|
||||
}
|
||||
if (k != NULL)
|
||||
{
|
||||
xmlFree(k);
|
||||
}
|
||||
if (value != NULL)
|
||||
{
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
else if (xmlStrEqual(childName, (const xmlChar *)"nd") == 1)
|
||||
{
|
||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||
if (ref != NULL)
|
||||
{
|
||||
way.path.push_back(stringToUint((const char *)ref));
|
||||
xmlFree(ref);
|
||||
}
|
||||
}
|
||||
xmlFree(childName);
|
||||
}
|
||||
}
|
||||
return way;
|
||||
}
|
||||
|
||||
ImportNode XMLParser::_ReadXMLNode() {
|
||||
ImportNode node;
|
||||
ImportNode XMLParser::ReadXMLNode()
|
||||
{
|
||||
ImportNode node;
|
||||
|
||||
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
|
||||
if ( attribute != NULL ) {
|
||||
node.lat = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ) );
|
||||
xmlFree( attribute );
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
|
||||
if ( attribute != NULL ) {
|
||||
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ));
|
||||
xmlFree( attribute );
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
||||
if ( attribute != NULL ) {
|
||||
node.id = stringToUint(( const char* ) attribute );
|
||||
xmlFree( attribute );
|
||||
}
|
||||
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
|
||||
if (attribute != NULL)
|
||||
{
|
||||
node.lat = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
||||
xmlFree(attribute);
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
|
||||
if (attribute != NULL)
|
||||
{
|
||||
node.lon = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
||||
xmlFree(attribute);
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||
if (attribute != NULL)
|
||||
{
|
||||
node.id = stringToUint((const char *)attribute);
|
||||
xmlFree(attribute);
|
||||
}
|
||||
|
||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||
const int depth = xmlTextReaderDepth( inputReader );
|
||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int childType = xmlTextReaderNodeType( inputReader );
|
||||
// 1 = Element, 15 = EndElement
|
||||
if ( childType != 1 && childType != 15 ) {
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||
if ( childName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
||||
{
|
||||
const int depth = xmlTextReaderDepth(inputReader);
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int childType = xmlTextReaderNodeType(inputReader);
|
||||
// 1 = Element, 15 = EndElement
|
||||
if (childType != 1 && childType != 15)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
||||
if (childName == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
|
||||
xmlFree( childName );
|
||||
break;
|
||||
}
|
||||
if ( childType != 1 ) {
|
||||
xmlFree( childName );
|
||||
continue;
|
||||
}
|
||||
if (depth == childDepth && childType == 15 &&
|
||||
xmlStrEqual(childName, (const xmlChar *)"node") == 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
break;
|
||||
}
|
||||
if (childType != 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||
if ( k != NULL && value != NULL ) {
|
||||
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
|
||||
}
|
||||
if ( k != NULL ) {
|
||||
xmlFree( k );
|
||||
}
|
||||
if ( value != NULL ) {
|
||||
xmlFree( value );
|
||||
}
|
||||
}
|
||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
||||
{
|
||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||
if (k != NULL && value != NULL)
|
||||
{
|
||||
node.keyVals.emplace(std::string((char *)(k)),
|
||||
std::string((char *)(value)));
|
||||
}
|
||||
if (k != NULL)
|
||||
{
|
||||
xmlFree(k);
|
||||
}
|
||||
if (value != NULL)
|
||||
{
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
|
||||
xmlFree( childName );
|
||||
}
|
||||
}
|
||||
return node;
|
||||
xmlFree(childName);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
+8
-12
@@ -33,21 +33,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
|
||||
class XMLParser : public BaseParser {
|
||||
public:
|
||||
XMLParser(
|
||||
const char* filename,
|
||||
ExtractorCallbacks* ec,
|
||||
ScriptingEnvironment& se
|
||||
);
|
||||
class XMLParser : public BaseParser
|
||||
{
|
||||
public:
|
||||
XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se);
|
||||
bool ReadHeader();
|
||||
bool Parse();
|
||||
|
||||
private:
|
||||
InputRestrictionContainer _ReadXMLRestriction();
|
||||
ExtractionWay _ReadXMLWay();
|
||||
ImportNode _ReadXMLNode();
|
||||
private:
|
||||
InputRestrictionContainer ReadXMLRestriction();
|
||||
ExtractionWay ReadXMLWay();
|
||||
ImportNode ReadXMLNode();
|
||||
xmlTextReaderPtr inputReader;
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef FIXED_POINT_COORDINATE_H_
|
||||
#define FIXED_POINT_COORDINATE_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <iosfwd> //for std::ostream
|
||||
|
||||
static const double COORDINATE_PRECISION = 1000000.;
|
||||
|
||||
@@ -37,7 +37,7 @@ struct FixedPointCoordinate {
|
||||
int lon;
|
||||
|
||||
FixedPointCoordinate();
|
||||
explicit FixedPointCoordinate (int lat, int lon);
|
||||
explicit FixedPointCoordinate( int lat, int lon);
|
||||
void Reset();
|
||||
bool isSet() const;
|
||||
bool isValid() const;
|
||||
@@ -74,11 +74,13 @@ struct FixedPointCoordinate {
|
||||
const FixedPointCoordinate & coord,
|
||||
std::string & output
|
||||
);
|
||||
|
||||
void Output(std::ostream & out) const;
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){
|
||||
out << "(" << c.lat << "," << c.lon << ")";
|
||||
return out;
|
||||
inline std::ostream& operator<<(std::ostream& o, FixedPointCoordinate const & c){
|
||||
c.Output(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||
|
||||
@@ -37,8 +37,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
namespace http {
|
||||
|
||||
const char okHTML[] = "";
|
||||
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
|
||||
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
|
||||
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
|
||||
const char internalServerErrorHTML[] = "{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
|
||||
const char seperators[] = { ':', ' ' };
|
||||
const char crlf[] = { '\r', '\n' };
|
||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
Reply();
|
||||
private:
|
||||
static std::string ToString(Reply::status_type status);
|
||||
std::string ToString(Reply::status_type status);
|
||||
boost::asio::const_buffer ToBuffer(Reply::status_type status);
|
||||
};
|
||||
|
||||
|
||||
+1
-3
@@ -28,8 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef OSRM_H
|
||||
#define OSRM_H
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
#include <osrm/ServerPaths.h>
|
||||
@@ -40,7 +38,7 @@ class OSRM {
|
||||
private:
|
||||
OSRM_impl * OSRM_pimpl_;
|
||||
public:
|
||||
OSRM(
|
||||
explicit OSRM(
|
||||
const ServerPaths & paths,
|
||||
const bool use_shared_memory = false
|
||||
);
|
||||
|
||||
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "OSRM.h"
|
||||
#include "OSRM_impl.h"
|
||||
#include "OSRM.h"
|
||||
|
||||
#include "../Plugins/HelloWorldPlugin.h"
|
||||
#include "../Plugins/LocatePlugin.h"
|
||||
|
||||
@@ -28,10 +28,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef BASEPLUGIN_H_
|
||||
#define BASEPLUGIN_H_
|
||||
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
template<class DataFacadeT>
|
||||
class LocatePlugin : public BasePlugin {
|
||||
public:
|
||||
LocatePlugin(DataFacadeT * facade)
|
||||
explicit LocatePlugin(DataFacadeT * facade)
|
||||
:
|
||||
descriptor_string("locate"),
|
||||
facade(facade)
|
||||
|
||||
@@ -41,7 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
template<class DataFacadeT>
|
||||
class NearestPlugin : public BasePlugin {
|
||||
public:
|
||||
NearestPlugin(DataFacadeT * facade )
|
||||
explicit NearestPlugin(DataFacadeT * facade )
|
||||
:
|
||||
facade(facade),
|
||||
descriptor_string("nearest")
|
||||
@@ -50,10 +50,9 @@ public:
|
||||
descriptorTable.emplace("json", 1);
|
||||
}
|
||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||
|
||||
void HandleRequest(
|
||||
const RouteParameters & routeParameters,
|
||||
http::Reply& reply
|
||||
http::Reply & reply
|
||||
) {
|
||||
//check number of parameters
|
||||
if(!routeParameters.coordinates.size()) {
|
||||
@@ -82,13 +81,13 @@ public:
|
||||
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.push_back("{\"status\":");
|
||||
if(UINT_MAX != result.edgeBasedNode) {
|
||||
if(UINT_MAX != result.forward_node_id) {
|
||||
reply.content.push_back("0,");
|
||||
} else {
|
||||
reply.content.push_back("207,");
|
||||
}
|
||||
reply.content.push_back("\"mapped_coordinate\":[");
|
||||
if(UINT_MAX != result.edgeBasedNode) {
|
||||
if(UINT_MAX != result.forward_node_id) {
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
|
||||
@@ -96,8 +95,8 @@ public:
|
||||
reply.content.push_back(temp_string);
|
||||
}
|
||||
reply.content.push_back("],\"name\":\"");
|
||||
if(UINT_MAX != result.edgeBasedNode) {
|
||||
facade->GetName(result.nodeBasedEdgeNameID, temp_string);
|
||||
if(UINT_MAX != result.forward_node_id) {
|
||||
facade->GetName(result.name_id, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
}
|
||||
reply.content.push_back("\"}");
|
||||
|
||||
@@ -33,7 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
template<class DataFacadeT>
|
||||
class TimestampPlugin : public BasePlugin {
|
||||
public:
|
||||
TimestampPlugin(const DataFacadeT * facade)
|
||||
explicit TimestampPlugin(const DataFacadeT * facade)
|
||||
: facade(facade), descriptor_string("timestamp")
|
||||
{ }
|
||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||
|
||||
+55
-67
@@ -39,6 +39,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
@@ -50,24 +52,21 @@ template<class DataFacadeT>
|
||||
class ViaRoutePlugin : public BasePlugin {
|
||||
private:
|
||||
boost::unordered_map<std::string, unsigned> descriptorTable;
|
||||
SearchEngine<DataFacadeT> * search_engine_ptr;
|
||||
boost::shared_ptr<SearchEngine<DataFacadeT> > search_engine_ptr;
|
||||
public:
|
||||
|
||||
ViaRoutePlugin(DataFacadeT * facade)
|
||||
explicit ViaRoutePlugin(DataFacadeT * facade)
|
||||
:
|
||||
descriptor_string("viaroute"),
|
||||
facade(facade)
|
||||
{
|
||||
//TODO: set up an engine for each thread!!
|
||||
search_engine_ptr = new SearchEngine<DataFacadeT>(facade);
|
||||
search_engine_ptr = boost::make_shared<SearchEngine<DataFacadeT> >(facade);
|
||||
|
||||
descriptorTable.emplace("json", 0);
|
||||
descriptorTable.emplace("gpx" , 1);
|
||||
}
|
||||
|
||||
virtual ~ViaRoutePlugin() {
|
||||
delete search_engine_ptr;
|
||||
}
|
||||
virtual ~ViaRoutePlugin() { }
|
||||
|
||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||
|
||||
@@ -81,115 +80,106 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
RawRouteData rawRoute;
|
||||
rawRoute.checkSum = facade->GetCheckSum();
|
||||
const bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
||||
RawRouteData raw_route;
|
||||
raw_route.checkSum = facade->GetCheckSum();
|
||||
const bool checksumOK = (routeParameters.checkSum == raw_route.checkSum);
|
||||
std::vector<std::string> textCoord;
|
||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||
if( !checkCoord(routeParameters.coordinates[i]) ) {
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
||||
raw_route.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
||||
}
|
||||
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
|
||||
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
|
||||
std::vector<PhantomNode> phantomNodeVector(raw_route.rawViaNodeCoordinates.size());
|
||||
for(unsigned i = 0; i < raw_route.rawViaNodeCoordinates.size(); ++i) {
|
||||
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
||||
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
|
||||
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
|
||||
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
|
||||
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
|
||||
facade->FindPhantomNodeForCoordinate(
|
||||
rawRoute.rawViaNodeCoordinates[i],
|
||||
raw_route.rawViaNodeCoordinates[i],
|
||||
phantomNodeVector[i],
|
||||
routeParameters.zoomLevel
|
||||
);
|
||||
}
|
||||
|
||||
PhantomNodes segmentPhantomNodes;
|
||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
||||
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
|
||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
||||
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
||||
PhantomNodes current_phantom_node_pair;
|
||||
for (unsigned i = 0; i < phantomNodeVector.size()-1; ++i)
|
||||
{
|
||||
current_phantom_node_pair.source_phantom = phantomNodeVector[i];
|
||||
current_phantom_node_pair.target_phantom = phantomNodeVector[i+1];
|
||||
raw_route.segmentEndCoordinates.push_back(current_phantom_node_pair);
|
||||
}
|
||||
|
||||
if(
|
||||
( routeParameters.alternateRoute ) &&
|
||||
(1 == rawRoute.segmentEndCoordinates.size())
|
||||
) {
|
||||
search_engine_ptr->alternative_path(
|
||||
rawRoute.segmentEndCoordinates[0],
|
||||
rawRoute
|
||||
);
|
||||
} else {
|
||||
search_engine_ptr->shortest_path(
|
||||
rawRoute.segmentEndCoordinates,
|
||||
rawRoute
|
||||
);
|
||||
if ((routeParameters.alternateRoute) && (1 == raw_route.segmentEndCoordinates.size()))
|
||||
{
|
||||
search_engine_ptr->alternative_path(raw_route.segmentEndCoordinates[0], raw_route);
|
||||
}
|
||||
else
|
||||
{
|
||||
search_engine_ptr->shortest_path(raw_route.segmentEndCoordinates, raw_route);
|
||||
}
|
||||
|
||||
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"Error occurred, single path not found";
|
||||
if (INT_MAX == raw_route.lengthOfShortestPath)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
//TODO: Move to member as smart pointer
|
||||
BaseDescriptor<DataFacadeT> * desc;
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
if (!routeParameters.jsonpParameter.empty())
|
||||
{
|
||||
reply.content.push_back(routeParameters.jsonpParameter);
|
||||
reply.content.push_back("(");
|
||||
}
|
||||
|
||||
DescriptorConfig descriptorConfig;
|
||||
DescriptorConfig descriptor_config;
|
||||
|
||||
unsigned descriptorType = 0;
|
||||
unsigned descriptor_type = 0;
|
||||
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
|
||||
descriptorType = descriptorTable.find(routeParameters.outputFormat)->second;
|
||||
descriptor_type = descriptorTable.find(routeParameters.outputFormat)->second;
|
||||
}
|
||||
descriptorConfig.zoom_level = routeParameters.zoomLevel;
|
||||
descriptorConfig.instructions = routeParameters.printInstructions;
|
||||
descriptorConfig.geometry = routeParameters.geometry;
|
||||
descriptorConfig.encode_geometry = routeParameters.compression;
|
||||
descriptor_config.zoom_level = routeParameters.zoomLevel;
|
||||
descriptor_config.instructions = routeParameters.printInstructions;
|
||||
descriptor_config.geometry = routeParameters.geometry;
|
||||
descriptor_config.encode_geometry = routeParameters.compression;
|
||||
|
||||
switch(descriptorType){
|
||||
boost::shared_ptr<BaseDescriptor<DataFacadeT> > descriptor;
|
||||
switch(descriptor_type){
|
||||
case 0:
|
||||
desc = new JSONDescriptor<DataFacadeT>();
|
||||
|
||||
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
|
||||
break;
|
||||
case 1:
|
||||
desc = new GPXDescriptor<DataFacadeT>();
|
||||
|
||||
descriptor = boost::make_shared<GPXDescriptor<DataFacadeT> >();
|
||||
break;
|
||||
default:
|
||||
desc = new JSONDescriptor<DataFacadeT>();
|
||||
|
||||
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
|
||||
break;
|
||||
}
|
||||
|
||||
PhantomNodes phantomNodes;
|
||||
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
||||
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
|
||||
desc->SetConfig(descriptorConfig);
|
||||
PhantomNodes phantom_nodes;
|
||||
phantom_nodes.source_phantom = raw_route.segmentEndCoordinates[0].source_phantom;
|
||||
phantom_nodes.target_phantom = raw_route.segmentEndCoordinates[raw_route.segmentEndCoordinates.size()-1].target_phantom;
|
||||
descriptor->SetConfig(descriptor_config);
|
||||
|
||||
desc->Run(rawRoute, phantomNodes, facade, reply);
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
descriptor->Run(raw_route, phantom_nodes, facade, reply);
|
||||
|
||||
if (!routeParameters.jsonpParameter.empty())
|
||||
{
|
||||
reply.content.push_back(")\n");
|
||||
}
|
||||
reply.headers.resize(3);
|
||||
reply.headers[0].name = "Content-Length";
|
||||
std::string tmp;
|
||||
unsigned content_length = 0;
|
||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||
content_length += snippet.length();
|
||||
}
|
||||
intToString(content_length, tmp);
|
||||
reply.headers[0].value = tmp;
|
||||
switch(descriptorType){
|
||||
std::string tmp_string;
|
||||
intToString(content_length, tmp_string);
|
||||
reply.headers[0].value = tmp_string;
|
||||
switch(descriptor_type){
|
||||
case 0:
|
||||
if( !routeParameters.jsonpParameter.empty() ){
|
||||
reply.headers[1].name = "Content-Type";
|
||||
@@ -225,8 +215,6 @@ public:
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
delete desc;
|
||||
return;
|
||||
}
|
||||
private:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,14 +30,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../DataStructures/RawRouteData.h"
|
||||
#include "../DataStructures/SearchEngineData.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
#include "../Util/ContainerUtils.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <climits>
|
||||
|
||||
#include <stack>
|
||||
|
||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
protected:
|
||||
DataFacadeT * facade;
|
||||
public:
|
||||
BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
|
||||
explicit BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
|
||||
virtual ~BasicRoutingInterface(){ };
|
||||
|
||||
inline void RoutingStep(
|
||||
@@ -62,57 +62,58 @@ public:
|
||||
SearchEngineData::QueryHeap & reverse_heap,
|
||||
NodeID * middle_node_id,
|
||||
int * upper_bound,
|
||||
const int edge_expansion_offset,
|
||||
const bool forward_direction
|
||||
) const {
|
||||
) const
|
||||
{
|
||||
const NodeID node = forward_heap.DeleteMin();
|
||||
const int distance = forward_heap.GetKey(node);
|
||||
//SimpleLogger().Write() << "Settled (" << forward_heap.GetData( node ).parent << "," << node << ")=" << distance;
|
||||
if(reverse_heap.WasInserted(node) ){
|
||||
if (reverse_heap.WasInserted(node))
|
||||
{
|
||||
const int new_distance = reverse_heap.GetKey(node) + distance;
|
||||
if(new_distance < *upper_bound ){
|
||||
if( new_distance >= 0 ) {
|
||||
if(new_distance < *upper_bound )
|
||||
{
|
||||
if (new_distance >= 0)
|
||||
{
|
||||
*middle_node_id = node;
|
||||
*upper_bound = new_distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (distance-edge_expansion_offset) > *upper_bound ){
|
||||
if (distance > *upper_bound)
|
||||
{
|
||||
forward_heap.DeleteAll();
|
||||
return;
|
||||
}
|
||||
|
||||
//Stalling
|
||||
for(
|
||||
EdgeID edge = facade->BeginEdges( node );
|
||||
edge < facade->EndEdges(node);
|
||||
++edge
|
||||
) {
|
||||
for (EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); ++edge)
|
||||
{
|
||||
const EdgeData & data = facade->GetEdgeData(edge);
|
||||
const bool reverse_flag = (!forward_direction) ? data.forward : data.backward;
|
||||
if( reverse_flag ) {
|
||||
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
||||
if (reverse_flag)
|
||||
{
|
||||
const NodeID to = facade->GetTarget(edge);
|
||||
const int edge_weight = data.distance;
|
||||
|
||||
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
|
||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||
|
||||
if(forward_heap.WasInserted( to )) {
|
||||
if(forward_heap.GetKey( to ) + edge_weight < distance) {
|
||||
if (forward_heap.WasInserted(to))
|
||||
{
|
||||
if(forward_heap.GetKey( to ) + edge_weight < distance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(
|
||||
EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node);
|
||||
edge < end_edge;
|
||||
++edge
|
||||
) {
|
||||
for (EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); edge < end_edge; ++edge)
|
||||
{
|
||||
const EdgeData & data = facade->GetEdgeData(edge);
|
||||
bool forward_directionFlag = (forward_direction ? data.forward : data.backward );
|
||||
if( forward_directionFlag ) {
|
||||
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
||||
if (forward_directionFlag)
|
||||
{
|
||||
|
||||
const NodeID to = facade->GetTarget(edge);
|
||||
const int edge_weight = data.distance;
|
||||
@@ -126,18 +127,19 @@ public:
|
||||
}
|
||||
//Found a shorter Path -> Update distance
|
||||
else if ( to_distance < forward_heap.GetKey( to ) ) {
|
||||
//new parent
|
||||
forward_heap.GetData( to ).parent = node;
|
||||
forward_heap.DecreaseKey( to, to_distance );
|
||||
//new parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void UnpackPath(
|
||||
const std::vector<NodeID> & packed_path,
|
||||
std::vector<PathData> & unpacked_path
|
||||
) const {
|
||||
inline void UnpackPath(const std::vector<NodeID> & packed_path, const PhantomNodes & phantom_node_pair, std::vector<PathData> & unpacked_path) const
|
||||
{
|
||||
const bool start_traversed_in_reverse = (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
|
||||
const bool target_traversed_in_reverse = (packed_path.back() != phantom_node_pair.target_phantom.forward_node_id);
|
||||
|
||||
const unsigned packed_path_size = packed_path.size();
|
||||
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||
|
||||
@@ -149,87 +151,170 @@ public:
|
||||
}
|
||||
|
||||
std::pair<NodeID, NodeID> edge;
|
||||
while(!recursion_stack.empty()) {
|
||||
while (!recursion_stack.empty())
|
||||
{
|
||||
edge = recursion_stack.top();
|
||||
recursion_stack.pop();
|
||||
|
||||
// facade->FindEdge does not suffice here in case of shortcuts.
|
||||
// The above explanation unclear? Think!
|
||||
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||
int edge_weight = INT_MAX;
|
||||
for(
|
||||
EdgeID edge_id = facade->BeginEdges(edge.first);
|
||||
edge_id < facade->EndEdges(edge.first);
|
||||
++edge_id
|
||||
){
|
||||
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
||||
{
|
||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||
if(
|
||||
(facade->GetTarget(edge_id) == edge.second) &&
|
||||
if ((facade->GetTarget(edge_id) == edge.second) &&
|
||||
(weight < edge_weight) &&
|
||||
facade->GetEdgeData(edge_id).forward
|
||||
){
|
||||
facade->GetEdgeData(edge_id).forward)
|
||||
{
|
||||
smaller_edge_id = edge_id;
|
||||
edge_weight = weight;
|
||||
}
|
||||
}
|
||||
|
||||
if( SPECIAL_EDGEID == smaller_edge_id ){
|
||||
for(
|
||||
EdgeID edge_id = facade->BeginEdges(edge.second);
|
||||
edge_id < facade->EndEdges(edge.second);
|
||||
++edge_id
|
||||
){
|
||||
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||
{
|
||||
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
||||
{
|
||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||
if(
|
||||
(facade->GetTarget(edge_id) == edge.first) &&
|
||||
(weight < edge_weight) &&
|
||||
facade->GetEdgeData(edge_id).backward
|
||||
){
|
||||
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
||||
{
|
||||
smaller_edge_id = edge_id;
|
||||
edge_weight = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge id invalid");
|
||||
BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid");
|
||||
|
||||
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
||||
if( ed.shortcut ) {//unpack
|
||||
const EdgeData & ed = facade->GetEdgeData(smaller_edge_id);
|
||||
if (ed.shortcut)
|
||||
{//unpack
|
||||
const NodeID middle_node_id = ed.id;
|
||||
//again, we need to this in reversed order
|
||||
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
||||
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
||||
} else {
|
||||
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be a shortcut");
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
|
||||
unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
|
||||
const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id);
|
||||
|
||||
if (!facade->EdgeIsCompressed(ed.id))
|
||||
{
|
||||
BOOST_ASSERT( !facade->EdgeIsCompressed(ed.id) );
|
||||
unpacked_path.push_back(
|
||||
PathData(
|
||||
facade->GetGeometryIndexForEdgeID(ed.id),
|
||||
name_index,
|
||||
turn_instruction,
|
||||
ed.distance
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<unsigned> id_vector;
|
||||
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id), id_vector);
|
||||
|
||||
const int start_index = ( unpacked_path.empty() ? ( ( start_traversed_in_reverse ) ? id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1 : phantom_node_pair.source_phantom.fwd_segment_position ) : 0 );
|
||||
const int end_index = id_vector.size();
|
||||
|
||||
BOOST_ASSERT(start_index >= 0);
|
||||
BOOST_ASSERT(start_index <= end_index);
|
||||
for (int i = start_index; i < end_index; ++i)
|
||||
{
|
||||
unpacked_path.push_back(
|
||||
PathData(
|
||||
id_vector[i],
|
||||
name_index,
|
||||
TurnInstructionsClass::NoTurn,
|
||||
0
|
||||
)
|
||||
);
|
||||
}
|
||||
unpacked_path.back().turnInstruction = turn_instruction;
|
||||
unpacked_path.back().durationOfSegment = ed.distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
|
||||
{
|
||||
std::vector<unsigned> id_vector;
|
||||
facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id, id_vector);
|
||||
if (target_traversed_in_reverse)
|
||||
{
|
||||
std::reverse(id_vector.begin(), id_vector.end() );
|
||||
}
|
||||
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id == phantom_node_pair.target_phantom.packed_geometry_id) && unpacked_path.empty();
|
||||
|
||||
int start_index = 0;
|
||||
int end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
||||
if (target_traversed_in_reverse)
|
||||
{
|
||||
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
|
||||
}
|
||||
if (is_local_path)
|
||||
{
|
||||
start_index = phantom_node_pair.source_phantom.fwd_segment_position;
|
||||
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
||||
if (target_traversed_in_reverse)
|
||||
{
|
||||
start_index = id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
|
||||
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_ASSERT(start_index >= 0);
|
||||
for (int i = start_index; i != end_index; (start_index < end_index ? ++i :--i))
|
||||
{
|
||||
BOOST_ASSERT( i >= -1 );
|
||||
unpacked_path.push_back(
|
||||
PathData(
|
||||
ed.id,
|
||||
facade->GetNameIndexFromEdgeID(ed.id),
|
||||
facade->GetTurnInstructionForEdgeID(ed.id),
|
||||
ed.distance
|
||||
id_vector[i],
|
||||
phantom_node_pair.target_phantom.name_id,
|
||||
TurnInstructionsClass::NoTurn,
|
||||
0
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// there is no equivalent to a node-based node in an edge-expanded graph.
|
||||
// two equivalent routes may start (or end) at different node-based edges
|
||||
// as they are added with the offset how much "distance" on the edge
|
||||
// has already been traversed. Depending on offset one needs to remove
|
||||
// the last node.
|
||||
if (unpacked_path.size() > 1)
|
||||
{
|
||||
const unsigned last_index = unpacked_path.size()-1;
|
||||
const unsigned second_to_last_index = last_index -1;
|
||||
|
||||
//looks like a trivially true check but tests for underflow
|
||||
BOOST_ASSERT(last_index > second_to_last_index);
|
||||
|
||||
if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node)
|
||||
{
|
||||
unpacked_path.pop_back();
|
||||
}
|
||||
BOOST_ASSERT(!unpacked_path.empty());
|
||||
}
|
||||
}
|
||||
|
||||
inline void UnpackEdge(
|
||||
const NodeID s,
|
||||
const NodeID t,
|
||||
std::vector<NodeID> & unpacked_path
|
||||
) const {
|
||||
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpacked_path) const
|
||||
{
|
||||
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||
recursion_stack.push(std::make_pair(s,t));
|
||||
|
||||
std::pair<NodeID, NodeID> edge;
|
||||
while(!recursion_stack.empty()) {
|
||||
while (!recursion_stack.empty())
|
||||
{
|
||||
edge = recursion_stack.top();
|
||||
recursion_stack.pop();
|
||||
|
||||
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||
int edge_weight = INT_MAX;
|
||||
for(
|
||||
EdgeID edge_id = facade->BeginEdges(edge.first);
|
||||
edge_id < facade->EndEdges(edge.first);
|
||||
++edge_id
|
||||
){
|
||||
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
||||
{
|
||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||
if(
|
||||
(facade->GetTarget(edge_id) == edge.second) &&
|
||||
@@ -241,18 +326,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if( SPECIAL_EDGEID == smaller_edge_id ){
|
||||
for(
|
||||
EdgeID edge_id = facade->BeginEdges(edge.second);
|
||||
edge_id < facade->EndEdges(edge.second);
|
||||
++edge_id
|
||||
){
|
||||
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||
{
|
||||
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
||||
{
|
||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||
if(
|
||||
(facade->GetTarget(edge_id) == edge.first) &&
|
||||
(weight < edge_weight) &&
|
||||
facade->GetEdgeData(edge_id).backward
|
||||
){
|
||||
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
||||
{
|
||||
smaller_edge_id = edge_id;
|
||||
edge_weight = weight;
|
||||
}
|
||||
@@ -261,16 +341,15 @@ public:
|
||||
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
|
||||
|
||||
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
||||
if(ed.shortcut) {//unpack
|
||||
if (ed.shortcut)
|
||||
{//unpack
|
||||
const NodeID middle_node_id = ed.id;
|
||||
//again, we need to this in reversed order
|
||||
recursion_stack.push(
|
||||
std::make_pair(middle_node_id, edge.second)
|
||||
);
|
||||
recursion_stack.push(
|
||||
std::make_pair(edge.first, middle_node_id)
|
||||
);
|
||||
} else {
|
||||
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
||||
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
|
||||
unpacked_path.push_back(edge.first );
|
||||
}
|
||||
@@ -279,43 +358,41 @@ public:
|
||||
}
|
||||
|
||||
inline void RetrievePackedPathFromHeap(
|
||||
SearchEngineData::QueryHeap & forward_heap,
|
||||
SearchEngineData::QueryHeap & reverse_heap,
|
||||
const SearchEngineData::QueryHeap & forward_heap,
|
||||
const SearchEngineData::QueryHeap & reverse_heap,
|
||||
const NodeID middle_node_id,
|
||||
std::vector<NodeID> & packed_path
|
||||
) const {
|
||||
) const
|
||||
{
|
||||
NodeID current_node_id = middle_node_id;
|
||||
while(current_node_id != forward_heap.GetData(current_node_id).parent) {
|
||||
while(current_node_id != forward_heap.GetData(current_node_id).parent)
|
||||
{
|
||||
current_node_id = forward_heap.GetData(current_node_id).parent;
|
||||
packed_path.push_back(current_node_id);
|
||||
}
|
||||
|
||||
std::reverse(packed_path.begin(), packed_path.end());
|
||||
packed_path.push_back(middle_node_id);
|
||||
current_node_id = middle_node_id;
|
||||
while (current_node_id != reverse_heap.GetData(current_node_id).parent){
|
||||
while (current_node_id != reverse_heap.GetData(current_node_id).parent)
|
||||
{
|
||||
current_node_id = reverse_heap.GetData(current_node_id).parent;
|
||||
packed_path.push_back(current_node_id);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: reorder parameters
|
||||
inline void RetrievePackedPathFromSingleHeap(
|
||||
SearchEngineData::QueryHeap & search_heap,
|
||||
const SearchEngineData::QueryHeap & search_heap,
|
||||
const NodeID middle_node_id,
|
||||
std::vector<NodeID>& packed_path
|
||||
) const {
|
||||
) const
|
||||
{
|
||||
NodeID current_node_id = middle_node_id;
|
||||
while(current_node_id != search_heap.GetData(current_node_id).parent) {
|
||||
while(current_node_id != search_heap.GetData(current_node_id).parent)
|
||||
{
|
||||
current_node_id = search_heap.GetData(current_node_id).parent;
|
||||
packed_path.push_back(current_node_id);
|
||||
}
|
||||
}
|
||||
|
||||
int ComputeEdgeOffset(const PhantomNode & phantom) const {
|
||||
return phantom.weight1 + (phantom.isBidirected() ? phantom.weight2 : 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* BASICROUTINGINTERFACE_H_ */
|
||||
|
||||
@@ -48,21 +48,22 @@ public:
|
||||
) :
|
||||
super(facade),
|
||||
engine_working_data(engine_working_data)
|
||||
{}
|
||||
{ }
|
||||
|
||||
~ShortestPathRouting() {}
|
||||
~ShortestPathRouting() { }
|
||||
|
||||
void operator()(
|
||||
const std::vector<PhantomNodes> & phantom_nodes_vector,
|
||||
RawRouteData & raw_route_data
|
||||
) const {
|
||||
) const
|
||||
{
|
||||
BOOST_FOREACH(
|
||||
const PhantomNodes & phantom_node_pair,
|
||||
phantom_nodes_vector
|
||||
){
|
||||
if(!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
||||
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||
if( phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ) {
|
||||
// raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||
// raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -104,71 +105,84 @@ public:
|
||||
middle2 = UINT_MAX;
|
||||
|
||||
//insert new starting nodes into forward heap, adjusted by previous distances.
|
||||
if(search_from_1st_node) {
|
||||
if(
|
||||
search_from_1st_node &&
|
||||
phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID
|
||||
) {
|
||||
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset();
|
||||
forward_heap1.Insert(
|
||||
phantom_node_pair.startPhantom.edgeBasedNode,
|
||||
distance1-phantom_node_pair.startPhantom.weight1,
|
||||
phantom_node_pair.startPhantom.edgeBasedNode
|
||||
phantom_node_pair.source_phantom.forward_node_id,
|
||||
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.forward_node_id
|
||||
);
|
||||
forward_heap2.Insert(
|
||||
phantom_node_pair.startPhantom.edgeBasedNode,
|
||||
distance1-phantom_node_pair.startPhantom.weight1,
|
||||
phantom_node_pair.startPhantom.edgeBasedNode
|
||||
phantom_node_pair.source_phantom.forward_node_id,
|
||||
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.forward_node_id
|
||||
);
|
||||
}
|
||||
if(phantom_node_pair.startPhantom.isBidirected() && search_from_2nd_node) {
|
||||
if(
|
||||
search_from_2nd_node &&
|
||||
phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID
|
||||
) {
|
||||
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
|
||||
forward_heap1.Insert(
|
||||
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
||||
distance2-phantom_node_pair.startPhantom.weight2,
|
||||
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||
phantom_node_pair.source_phantom.reverse_node_id,
|
||||
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.reverse_node_id
|
||||
);
|
||||
forward_heap2.Insert(
|
||||
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
||||
distance2-phantom_node_pair.startPhantom.weight2,
|
||||
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||
phantom_node_pair.source_phantom.reverse_node_id,
|
||||
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.reverse_node_id
|
||||
);
|
||||
}
|
||||
|
||||
//insert new backward nodes into backward heap, unadjusted.
|
||||
reverse_heap1.Insert(
|
||||
phantom_node_pair.targetPhantom.edgeBasedNode,
|
||||
phantom_node_pair.targetPhantom.weight1,
|
||||
phantom_node_pair.targetPhantom.edgeBasedNode
|
||||
);
|
||||
if(phantom_node_pair.targetPhantom.isBidirected() ) {
|
||||
reverse_heap2.Insert(
|
||||
phantom_node_pair.targetPhantom.edgeBasedNode+1,
|
||||
phantom_node_pair.targetPhantom.weight2,
|
||||
phantom_node_pair.targetPhantom.edgeBasedNode+1
|
||||
if( phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID ) {
|
||||
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset();
|
||||
reverse_heap1.Insert(
|
||||
phantom_node_pair.target_phantom.forward_node_id,
|
||||
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
|
||||
phantom_node_pair.target_phantom.forward_node_id
|
||||
);
|
||||
}
|
||||
|
||||
const int forward_offset = super::ComputeEdgeOffset(
|
||||
phantom_node_pair.startPhantom
|
||||
);
|
||||
const int reverse_offset = super::ComputeEdgeOffset(
|
||||
phantom_node_pair.targetPhantom
|
||||
);
|
||||
if( phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID ) {
|
||||
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset();
|
||||
reverse_heap2.Insert(
|
||||
phantom_node_pair.target_phantom.reverse_node_id,
|
||||
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
|
||||
phantom_node_pair.target_phantom.reverse_node_id
|
||||
);
|
||||
}
|
||||
|
||||
// const int forward_offset = phantom_node_pair.ComputeForwardQueueOffset();
|
||||
// const int forward_offset = super::ComputeForwardOffset(
|
||||
// phantom_node_pair.source_phantom
|
||||
// );
|
||||
// const int reverse_offset = -phantom_node_pair.ComputeReverseQueueOffset();
|
||||
// const int reverse_offset = super::ComputeReverseOffset(
|
||||
// phantom_node_pair.target_phantom
|
||||
// );
|
||||
|
||||
//run two-Target Dijkstra routing step.
|
||||
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
||||
if( !forward_heap1.Empty()){
|
||||
if( 0 < forward_heap1.Size() ){
|
||||
super::RoutingStep(
|
||||
forward_heap1,
|
||||
reverse_heap1,
|
||||
&middle1,
|
||||
&local_upper_bound1,
|
||||
forward_offset,
|
||||
true
|
||||
);
|
||||
}
|
||||
if( !reverse_heap1.Empty() ){
|
||||
if( 0 < reverse_heap1.Size() ){
|
||||
super::RoutingStep(
|
||||
reverse_heap1,
|
||||
forward_heap1,
|
||||
&middle1,
|
||||
&local_upper_bound1,
|
||||
reverse_offset,
|
||||
false
|
||||
);
|
||||
}
|
||||
@@ -176,23 +190,21 @@ public:
|
||||
|
||||
if( !reverse_heap2.Empty() ) {
|
||||
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
||||
if( !forward_heap2.Empty() ){
|
||||
if( 0 < forward_heap2.Size() ){
|
||||
super::RoutingStep(
|
||||
forward_heap2,
|
||||
reverse_heap2,
|
||||
&middle2,
|
||||
&local_upper_bound2,
|
||||
forward_offset,
|
||||
true
|
||||
);
|
||||
}
|
||||
if( !reverse_heap2.Empty() ){
|
||||
if( 0 < reverse_heap2.Size() ){
|
||||
super::RoutingStep(
|
||||
reverse_heap2,
|
||||
forward_heap2,
|
||||
&middle2,
|
||||
&local_upper_bound2,
|
||||
reverse_offset,
|
||||
false
|
||||
);
|
||||
}
|
||||
@@ -201,17 +213,17 @@ public:
|
||||
|
||||
//No path found for both target nodes?
|
||||
if(
|
||||
(INT_MAX == local_upper_bound1) &&
|
||||
(INT_MAX == local_upper_bound2)
|
||||
(INVALID_EDGE_WEIGHT == local_upper_bound1) &&
|
||||
(INVALID_EDGE_WEIGHT == local_upper_bound2)
|
||||
) {
|
||||
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||
raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT;
|
||||
raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT;
|
||||
return;
|
||||
}
|
||||
if(UINT_MAX == middle1) {
|
||||
if( SPECIAL_NODEID == middle1 ) {
|
||||
search_from_1st_node = false;
|
||||
}
|
||||
if(UINT_MAX == middle2) {
|
||||
if( SPECIAL_NODEID == middle2 ) {
|
||||
search_from_2nd_node = false;
|
||||
}
|
||||
|
||||
@@ -228,7 +240,7 @@ public:
|
||||
BOOST_ASSERT( (unsigned)current_leg < packed_legs1.size() );
|
||||
BOOST_ASSERT( (unsigned)current_leg < packed_legs2.size() );
|
||||
|
||||
if(INT_MAX != local_upper_bound1) {
|
||||
if( INVALID_EDGE_WEIGHT != local_upper_bound1 ) {
|
||||
super::RetrievePackedPathFromHeap(
|
||||
forward_heap1,
|
||||
reverse_heap1,
|
||||
@@ -237,7 +249,7 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
if(INT_MAX != local_upper_bound2) {
|
||||
if( INVALID_EDGE_WEIGHT != local_upper_bound2 ) {
|
||||
super::RetrievePackedPathFromHeap(
|
||||
forward_heap2,
|
||||
reverse_heap2,
|
||||
@@ -264,8 +276,6 @@ public:
|
||||
local_upper_bound2 = local_upper_bound1;
|
||||
}
|
||||
|
||||
// SimpleLogger().Write() << "fetched packed paths";
|
||||
|
||||
BOOST_ASSERT_MSG(
|
||||
!temporary_packed_leg1.empty() ||
|
||||
!temporary_packed_leg2.empty(),
|
||||
@@ -335,11 +345,11 @@ public:
|
||||
|
||||
if(
|
||||
(packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
|
||||
phantom_node_pair.targetPhantom.isBidirected()
|
||||
phantom_node_pair.target_phantom.isBidirected()
|
||||
) {
|
||||
const NodeID last_node_id = packed_legs2[current_leg].back();
|
||||
search_from_1st_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode+1);
|
||||
search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode);
|
||||
search_from_1st_node &= !(last_node_id == phantom_node_pair.target_phantom.reverse_node_id);
|
||||
search_from_2nd_node &= !(last_node_id == phantom_node_pair.target_phantom.forward_node_id);
|
||||
BOOST_ASSERT( search_from_1st_node != search_from_2nd_node );
|
||||
}
|
||||
|
||||
@@ -348,14 +358,42 @@ public:
|
||||
++current_leg;
|
||||
}
|
||||
|
||||
if( distance1 > distance2 ) {
|
||||
if (distance1 > distance2)
|
||||
{
|
||||
std::swap( packed_legs1, packed_legs2 );
|
||||
}
|
||||
raw_route_data.unpacked_path_segments.resize( packed_legs1.size() );
|
||||
for(unsigned i = 0; i < packed_legs1.size(); ++i){
|
||||
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size() );
|
||||
// const int start_offset = ( packed_legs1[0].front() == phantom_nodes_vector.front().source_phantom.forward_node_id ? 1 : -1 )*phantom_nodes_vector.front().source_phantom.fwd_segment_position;
|
||||
|
||||
raw_route_data.source_traversed_in_reverse = (packed_legs1.front().front() != phantom_nodes_vector.front().source_phantom.forward_node_id);
|
||||
raw_route_data.target_traversed_in_reverse = (packed_legs1.back().back() != phantom_nodes_vector.back().target_phantom.forward_node_id);
|
||||
|
||||
for (unsigned i = 0; i < packed_legs1.size(); ++i)
|
||||
{
|
||||
BOOST_ASSERT(!phantom_nodes_vector.empty());
|
||||
// const bool at_beginning = (packed_legs1[i] == packed_legs1.front());
|
||||
// const bool at_end = (packed_legs1[i] == packed_legs1.back());
|
||||
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size());
|
||||
|
||||
PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i];
|
||||
// if (!at_beginning)
|
||||
// {
|
||||
// unpack_phantom_node_pair.source_phantom.packed_geometry_id = SPECIAL_EDGEID;
|
||||
// unpack_phantom_node_pair.source_phantom.fwd_segment_position = 0;
|
||||
// }
|
||||
|
||||
// if (!at_end)
|
||||
// {
|
||||
// unpack_phantom_node_pair.target_phantom.packed_geometry_id = SPECIAL_EDGEID;
|
||||
// unpack_phantom_node_pair.target_phantom.fwd_segment_position = 0;
|
||||
// }
|
||||
|
||||
super::UnpackPath(
|
||||
// -- packed input
|
||||
packed_legs1[i],
|
||||
// -- start and end of (sub-)route
|
||||
unpack_phantom_node_pair,
|
||||
// -- unpacked output
|
||||
raw_route_data.unpacked_path_segments[i]
|
||||
);
|
||||
}
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ namespace qi = boost::spirit::qi;
|
||||
|
||||
template <typename Iterator, class HandlerT>
|
||||
struct APIGrammar : qi::grammar<Iterator> {
|
||||
APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
|
||||
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
|
||||
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
|
||||
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
|
||||
|
||||
|
||||
@@ -86,6 +86,15 @@ public:
|
||||
const unsigned id
|
||||
) const = 0;
|
||||
|
||||
virtual bool EdgeIsCompressed( const unsigned id ) const = 0;
|
||||
|
||||
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0;
|
||||
|
||||
virtual void GetUncompressedGeometry(
|
||||
const unsigned id,
|
||||
std::vector<unsigned> & result_nodes
|
||||
) const = 0;
|
||||
|
||||
virtual TurnInstruction GetTurnInstructionForEdgeID(
|
||||
const unsigned id
|
||||
) const = 0;
|
||||
|
||||
@@ -45,6 +45,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
template<class EdgeDataT>
|
||||
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
|
||||
|
||||
@@ -61,14 +64,23 @@ private:
|
||||
QueryGraph * m_query_graph;
|
||||
std::string m_timestamp;
|
||||
|
||||
ShM<FixedPointCoordinate, false>::vector m_coordinate_list;
|
||||
boost::shared_ptr<ShM<FixedPointCoordinate, false>::vector> m_coordinate_list;
|
||||
ShM<NodeID, false>::vector m_via_node_list;
|
||||
ShM<unsigned, false>::vector m_name_ID_list;
|
||||
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
|
||||
ShM<char, false>::vector m_names_char_list;
|
||||
ShM<unsigned, false>::vector m_name_begin_indices;
|
||||
ShM<bool, false>::vector m_egde_is_compressed;
|
||||
ShM<unsigned, false>::vector m_geometry_indices;
|
||||
ShM<unsigned, false>::vector m_geometry_list;
|
||||
|
||||
StaticRTree<RTreeLeaf, false> * m_static_rtree;
|
||||
boost::shared_ptr<
|
||||
StaticRTree<
|
||||
RTreeLeaf,
|
||||
ShM<FixedPointCoordinate, false>::vector,
|
||||
false
|
||||
>
|
||||
> m_static_rtree;
|
||||
|
||||
|
||||
void LoadTimestamp(const boost::filesystem::path & timestamp_path) {
|
||||
@@ -103,7 +115,7 @@ private:
|
||||
);
|
||||
|
||||
BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty");
|
||||
BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
|
||||
// BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
|
||||
SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() << " edges";
|
||||
m_query_graph = new QueryGraph(node_list, edge_list);
|
||||
|
||||
@@ -113,42 +125,44 @@ private:
|
||||
}
|
||||
|
||||
void LoadNodeAndEdgeInformation(
|
||||
const boost::filesystem::path nodes_file,
|
||||
const boost::filesystem::path edges_file
|
||||
const boost::filesystem::path & nodes_file,
|
||||
const boost::filesystem::path & edges_file
|
||||
) {
|
||||
boost::filesystem::ifstream nodes_input_stream(
|
||||
nodes_file,
|
||||
std::ios::binary
|
||||
);
|
||||
|
||||
SimpleLogger().Write(logDEBUG) << "Loading node data";
|
||||
NodeInfo current_node;
|
||||
unsigned number_of_coordinates = 0;
|
||||
nodes_input_stream.read(
|
||||
(char *)&number_of_coordinates,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
m_coordinate_list.resize(number_of_coordinates);
|
||||
m_coordinate_list = boost::make_shared<std::vector<FixedPointCoordinate> >(number_of_coordinates);
|
||||
for(unsigned i = 0; i < number_of_coordinates; ++i) {
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
||||
m_coordinate_list[i] = FixedPointCoordinate(
|
||||
m_coordinate_list->at(i) = FixedPointCoordinate(
|
||||
current_node.lat,
|
||||
current_node.lon
|
||||
);
|
||||
BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lat) >> 30) == 0 );
|
||||
BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lon) >> 30) == 0 );
|
||||
}
|
||||
std::vector<FixedPointCoordinate>(m_coordinate_list).swap(m_coordinate_list);
|
||||
nodes_input_stream.close();
|
||||
|
||||
SimpleLogger().Write(logDEBUG) << "Loading edge data";
|
||||
boost::filesystem::ifstream edges_input_stream(
|
||||
edges_file,
|
||||
std::ios::binary
|
||||
);
|
||||
unsigned number_of_edges = 0;
|
||||
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
|
||||
m_via_node_list.resize(number_of_edges);
|
||||
m_name_ID_list.resize(number_of_edges);
|
||||
m_via_node_list.resize (number_of_edges);
|
||||
m_name_ID_list.resize (number_of_edges);
|
||||
m_turn_instruction_list.resize(number_of_edges);
|
||||
m_egde_is_compressed.resize (number_of_edges);
|
||||
|
||||
unsigned compressed = 0;
|
||||
|
||||
OriginalEdgeData current_edge_data;
|
||||
for(unsigned i = 0; i < number_of_edges; ++i) {
|
||||
@@ -159,17 +173,63 @@ private:
|
||||
m_via_node_list[i] = current_edge_data.via_node;
|
||||
m_name_ID_list[i] = current_edge_data.name_id;
|
||||
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
|
||||
m_egde_is_compressed[i] = current_edge_data.compressed_geometry;
|
||||
if(m_egde_is_compressed[i]) {
|
||||
++compressed;
|
||||
}
|
||||
}
|
||||
|
||||
edges_input_stream.close();
|
||||
}
|
||||
|
||||
void LoadGeometries(const boost::filesystem::path & geometry_file)
|
||||
{
|
||||
std::ifstream geometry_stream(
|
||||
geometry_file.c_str(),
|
||||
std::ios::binary
|
||||
);
|
||||
unsigned number_of_indices = 0;
|
||||
unsigned number_of_compressed_geometries = 0;
|
||||
|
||||
geometry_stream.read(
|
||||
(char *)&number_of_indices,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
|
||||
m_geometry_indices.resize(number_of_indices);
|
||||
geometry_stream.read(
|
||||
(char *)&(m_geometry_indices[0]),
|
||||
number_of_indices*sizeof(unsigned)
|
||||
);
|
||||
|
||||
geometry_stream.read(
|
||||
(char *)&number_of_compressed_geometries,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
|
||||
BOOST_ASSERT( m_geometry_indices.back() == number_of_compressed_geometries );
|
||||
m_geometry_list.resize( number_of_compressed_geometries );
|
||||
|
||||
geometry_stream.read(
|
||||
(char *)&(m_geometry_list[0]),
|
||||
number_of_compressed_geometries*sizeof(unsigned)
|
||||
);
|
||||
geometry_stream.close();
|
||||
}
|
||||
|
||||
void LoadRTree(
|
||||
const boost::filesystem::path & ram_index_path,
|
||||
const boost::filesystem::path & file_index_path
|
||||
) {
|
||||
m_static_rtree = new StaticRTree<RTreeLeaf>(
|
||||
BOOST_ASSERT_MSG(
|
||||
!m_coordinate_list->empty(),
|
||||
"coordinates must be loaded before r-tree"
|
||||
);
|
||||
|
||||
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf> >(
|
||||
ram_index_path,
|
||||
file_index_path
|
||||
file_index_path,
|
||||
m_coordinate_list
|
||||
);
|
||||
}
|
||||
|
||||
@@ -204,10 +264,10 @@ private:
|
||||
public:
|
||||
~InternalDataFacade() {
|
||||
delete m_query_graph;
|
||||
delete m_static_rtree;
|
||||
m_static_rtree.reset();
|
||||
}
|
||||
|
||||
InternalDataFacade( const ServerPaths & server_paths ) {
|
||||
explicit InternalDataFacade( const ServerPaths & server_paths ) {
|
||||
//generate paths of data files
|
||||
if( server_paths.find("hsgrdata") == server_paths.end() ) {
|
||||
throw OSRMException("no hsgr file given in ini file");
|
||||
@@ -218,6 +278,9 @@ public:
|
||||
if( server_paths.find("fileindex") == server_paths.end() ) {
|
||||
throw OSRMException("no leaf index file given in ini file");
|
||||
}
|
||||
if( server_paths.find("geometries") == server_paths.end() ) {
|
||||
throw OSRMException("no geometries file given in ini file");
|
||||
}
|
||||
if( server_paths.find("nodesdata") == server_paths.end() ) {
|
||||
throw OSRMException("no nodes file given in ini file");
|
||||
}
|
||||
@@ -249,12 +312,17 @@ public:
|
||||
paths_iterator = server_paths.find("namesdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & names_data_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("geometries");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & geometries_path = paths_iterator->second;
|
||||
|
||||
//load data
|
||||
SimpleLogger().Write() << "loading graph data";
|
||||
LoadGraph(hsgr_path);
|
||||
SimpleLogger().Write() << "loading egde information";
|
||||
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
|
||||
SimpleLogger().Write() << "loading geometries";
|
||||
LoadGeometries( geometries_path );
|
||||
SimpleLogger().Write() << "loading r-tree";
|
||||
LoadRTree(ram_index_path, file_index_path);
|
||||
SimpleLogger().Write() << "loading timestamp";
|
||||
@@ -319,10 +387,13 @@ public:
|
||||
FixedPointCoordinate GetCoordinateOfNode(
|
||||
const unsigned id
|
||||
) const {
|
||||
const NodeID node = m_via_node_list.at(id);
|
||||
return m_coordinate_list.at(node);
|
||||
return m_coordinate_list->at(id);
|
||||
};
|
||||
|
||||
bool EdgeIsCompressed( const unsigned id ) const {
|
||||
return m_egde_is_compressed.at(id);
|
||||
}
|
||||
|
||||
TurnInstruction GetTurnInstructionForEdgeID(
|
||||
const unsigned id
|
||||
) const {
|
||||
@@ -346,11 +417,12 @@ public:
|
||||
PhantomNode & resulting_phantom_node,
|
||||
const unsigned zoom_level
|
||||
) const {
|
||||
return m_static_rtree->FindPhantomNodeForCoordinate(
|
||||
input_coordinate,
|
||||
resulting_phantom_node,
|
||||
zoom_level
|
||||
);
|
||||
const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
|
||||
input_coordinate,
|
||||
resulting_phantom_node,
|
||||
zoom_level
|
||||
);
|
||||
return found;
|
||||
}
|
||||
|
||||
unsigned GetCheckSum() const { return m_check_sum; }
|
||||
@@ -368,8 +440,8 @@ public:
|
||||
name_id < m_name_begin_indices.size(),
|
||||
"name id too high"
|
||||
);
|
||||
unsigned begin_index = m_name_begin_indices[name_id];
|
||||
unsigned end_index = m_name_begin_indices[name_id+1];
|
||||
const unsigned begin_index = m_name_begin_indices[name_id];
|
||||
const unsigned end_index = m_name_begin_indices[name_id+1];
|
||||
BOOST_ASSERT_MSG(
|
||||
begin_index < m_names_char_list.size(),
|
||||
"begin index of name too high"
|
||||
@@ -389,6 +461,22 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const {
|
||||
return m_via_node_list.at(id);
|
||||
}
|
||||
|
||||
virtual void GetUncompressedGeometry(
|
||||
const unsigned id, std::vector<unsigned> & result_nodes
|
||||
) const {
|
||||
const unsigned begin = m_geometry_indices.at(id);
|
||||
const unsigned end = m_geometry_indices.at(id+1);
|
||||
|
||||
result_nodes.clear();
|
||||
result_nodes.insert(result_nodes.begin(),
|
||||
m_geometry_list.begin() + begin,
|
||||
m_geometry_list.begin() + end);
|
||||
}
|
||||
|
||||
std::string GetTimestamp() const {
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
@@ -30,9 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//implements all data storage when shared memory _IS_ used
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "BaseDataFacade.h"
|
||||
#include "SharedDataType.h"
|
||||
|
||||
@@ -42,6 +39,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../../Util/ProgramOptions.h"
|
||||
#include "../../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template<class EdgeDataT>
|
||||
@@ -55,7 +55,7 @@ private:
|
||||
typedef typename StaticGraph<EdgeData, true>::_StrEdge GraphEdge;
|
||||
typedef typename QueryGraph::InputEdge InputEdge;
|
||||
typedef typename super::RTreeLeaf RTreeLeaf;
|
||||
typedef typename StaticRTree<RTreeLeaf, true>::TreeNode RTreeNode;
|
||||
typedef typename StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode RTreeNode;
|
||||
|
||||
SharedDataLayout * data_layout;
|
||||
char * shared_memory;
|
||||
@@ -72,15 +72,25 @@ private:
|
||||
boost::shared_ptr<SharedMemory> m_large_memory;
|
||||
std::string m_timestamp;
|
||||
|
||||
ShM<FixedPointCoordinate, true>::vector m_coordinate_list;
|
||||
boost::shared_ptr<
|
||||
ShM<FixedPointCoordinate, true>::vector
|
||||
> m_coordinate_list;
|
||||
ShM<NodeID, true>::vector m_via_node_list;
|
||||
ShM<unsigned, true>::vector m_name_ID_list;
|
||||
ShM<TurnInstruction, true>::vector m_turn_instruction_list;
|
||||
ShM<char, true>::vector m_names_char_list;
|
||||
ShM<unsigned, true>::vector m_name_begin_indices;
|
||||
boost::shared_ptr<StaticRTree<RTreeLeaf, true> > m_static_rtree;
|
||||
ShM<bool, true>::vector m_egde_is_compressed;
|
||||
ShM<unsigned, true>::vector m_geometry_indices;
|
||||
ShM<unsigned, true>::vector m_geometry_list;
|
||||
|
||||
// SharedDataFacade() { }
|
||||
boost::shared_ptr<
|
||||
StaticRTree<
|
||||
RTreeLeaf,
|
||||
ShM<FixedPointCoordinate, true>::vector,
|
||||
true
|
||||
>
|
||||
> m_static_rtree;
|
||||
|
||||
void LoadTimestamp() {
|
||||
char * timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset();
|
||||
@@ -95,13 +105,19 @@ private:
|
||||
void LoadRTree(
|
||||
const boost::filesystem::path & file_index_path
|
||||
) {
|
||||
BOOST_ASSERT_MSG(
|
||||
!m_coordinate_list->empty(),
|
||||
"coordinates must be loaded before r-tree"
|
||||
);
|
||||
|
||||
RTreeNode * tree_ptr = (RTreeNode *)(
|
||||
shared_memory + data_layout->GetRSearchTreeOffset()
|
||||
);
|
||||
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf, true> >(
|
||||
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true> >(
|
||||
tree_ptr,
|
||||
data_layout->r_search_tree_size,
|
||||
file_index_path
|
||||
file_index_path,
|
||||
m_coordinate_list
|
||||
);
|
||||
}
|
||||
|
||||
@@ -112,7 +128,7 @@ private:
|
||||
);
|
||||
|
||||
GraphEdge * graph_edges_ptr = (GraphEdge *)(
|
||||
shared_memory + data_layout->GetGraphEdgeListOffsett()
|
||||
shared_memory + data_layout->GetGraphEdgeListOffset()
|
||||
);
|
||||
|
||||
typename ShM<GraphNode, true>::vector node_list(
|
||||
@@ -126,7 +142,6 @@ private:
|
||||
m_query_graph.reset(
|
||||
new QueryGraph(node_list, edge_list)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void LoadNodeAndEdgeInformation() {
|
||||
@@ -134,11 +149,10 @@ private:
|
||||
FixedPointCoordinate * coordinate_list_ptr = (FixedPointCoordinate *)(
|
||||
shared_memory + data_layout->GetCoordinateListOffset()
|
||||
);
|
||||
typename ShM<FixedPointCoordinate, true>::vector coordinate_list(
|
||||
m_coordinate_list = boost::make_shared<ShM<FixedPointCoordinate, true>::vector> (
|
||||
coordinate_list_ptr,
|
||||
data_layout->coordinate_list_size
|
||||
);
|
||||
m_coordinate_list.swap( coordinate_list );
|
||||
|
||||
TurnInstruction * turn_instruction_list_ptr = (TurnInstruction *)(
|
||||
shared_memory + data_layout->GetTurnInstructionListOffset()
|
||||
@@ -190,6 +204,36 @@ private:
|
||||
m_names_char_list.swap(names_char_list);
|
||||
}
|
||||
|
||||
void LoadGeometries()
|
||||
{
|
||||
unsigned * geometries_compressed_ptr = (unsigned *)(
|
||||
shared_memory + data_layout->GetGeometriesIndicatorOffset()
|
||||
);
|
||||
typename ShM<bool, true>::vector egde_is_compressed(
|
||||
geometries_compressed_ptr,
|
||||
data_layout->geometries_indicators
|
||||
);
|
||||
m_egde_is_compressed.swap(egde_is_compressed);
|
||||
|
||||
unsigned * geometries_index_ptr = (unsigned *)(
|
||||
shared_memory + data_layout->GetGeometriesIndexListOffset()
|
||||
);
|
||||
typename ShM<unsigned, true>::vector geometry_begin_indices(
|
||||
geometries_index_ptr,
|
||||
data_layout->geometries_index_list_size
|
||||
);
|
||||
m_geometry_indices.swap(geometry_begin_indices);
|
||||
|
||||
unsigned * geometries_list_ptr = (unsigned *)(
|
||||
shared_memory + data_layout->GetGeometryListOffset()
|
||||
);
|
||||
typename ShM<unsigned, true>::vector geometry_list(
|
||||
geometries_list_ptr,
|
||||
data_layout->geometries_list_size
|
||||
);
|
||||
m_geometry_list.swap(geometry_list);
|
||||
}
|
||||
|
||||
public:
|
||||
SharedDataFacade( ) {
|
||||
data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
|
||||
@@ -241,6 +285,7 @@ public:
|
||||
|
||||
LoadGraph();
|
||||
LoadNodeAndEdgeInformation();
|
||||
LoadGeometries();
|
||||
LoadRTree(ram_index_path);
|
||||
LoadTimestamp();
|
||||
LoadViaNodeList();
|
||||
@@ -250,7 +295,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//search graph access
|
||||
unsigned GetNumberOfNodes() const {
|
||||
return m_query_graph->GetNumberOfNodes();
|
||||
@@ -307,10 +351,29 @@ public:
|
||||
FixedPointCoordinate GetCoordinateOfNode(
|
||||
const unsigned id
|
||||
) const {
|
||||
const NodeID node = m_via_node_list.at(id);
|
||||
return m_coordinate_list.at(node);
|
||||
return m_coordinate_list->at(id);
|
||||
};
|
||||
|
||||
virtual bool EdgeIsCompressed( const unsigned id ) const {
|
||||
return m_egde_is_compressed.at(id);
|
||||
}
|
||||
|
||||
virtual void GetUncompressedGeometry(
|
||||
const unsigned id, std::vector<unsigned> & result_nodes
|
||||
) const {
|
||||
const unsigned begin = m_geometry_indices.at(id);
|
||||
const unsigned end = m_geometry_indices.at(id+1);
|
||||
|
||||
result_nodes.clear();
|
||||
result_nodes.insert(result_nodes.begin(),
|
||||
m_geometry_list.begin() + begin,
|
||||
m_geometry_list.begin() + end);
|
||||
}
|
||||
|
||||
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const {
|
||||
return m_via_node_list.at(id);
|
||||
}
|
||||
|
||||
TurnInstruction GetTurnInstructionForEdgeID(
|
||||
const unsigned id
|
||||
) const {
|
||||
@@ -334,11 +397,12 @@ public:
|
||||
PhantomNode & resulting_phantom_node,
|
||||
const unsigned zoom_level
|
||||
) const {
|
||||
return m_static_rtree->FindPhantomNodeForCoordinate(
|
||||
input_coordinate,
|
||||
resulting_phantom_node,
|
||||
zoom_level
|
||||
);
|
||||
const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
|
||||
input_coordinate,
|
||||
resulting_phantom_node,
|
||||
zoom_level
|
||||
);
|
||||
return found;
|
||||
}
|
||||
|
||||
unsigned GetCheckSum() const { return m_check_sum; }
|
||||
|
||||
@@ -43,7 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/integer.hpp>
|
||||
|
||||
typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf;
|
||||
typedef StaticRTree<RTreeLeaf, true>::TreeNode RTreeNode;
|
||||
typedef StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode RTreeNode;
|
||||
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||
|
||||
struct SharedDataLayout {
|
||||
@@ -56,6 +56,9 @@ struct SharedDataLayout {
|
||||
uint64_t coordinate_list_size;
|
||||
uint64_t turn_instruction_list_size;
|
||||
uint64_t r_search_tree_size;
|
||||
uint64_t geometries_index_list_size;
|
||||
uint64_t geometries_list_size;
|
||||
uint64_t geometries_indicators;
|
||||
|
||||
unsigned checksum;
|
||||
unsigned timestamp_length;
|
||||
@@ -72,8 +75,12 @@ struct SharedDataLayout {
|
||||
coordinate_list_size(0),
|
||||
turn_instruction_list_size(0),
|
||||
r_search_tree_size(0),
|
||||
geometries_index_list_size(0),
|
||||
geometries_list_size(0),
|
||||
geometries_indicators(0),
|
||||
checksum(0),
|
||||
timestamp_length(0)
|
||||
|
||||
{
|
||||
ram_index_file_name[0] = '\0';
|
||||
}
|
||||
@@ -90,23 +97,29 @@ struct SharedDataLayout {
|
||||
SimpleLogger().Write(logDEBUG) << "coordinate_list_size: " << coordinate_list_size;
|
||||
SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << turn_instruction_list_size;
|
||||
SimpleLogger().Write(logDEBUG) << "r_search_tree_size: " << r_search_tree_size;
|
||||
SimpleLogger().Write(logDEBUG) << "geometries_indicators: " << geometries_indicators << "/" << ((geometries_indicators/8) + 1);
|
||||
SimpleLogger().Write(logDEBUG) << "geometries_index_list_size: " << geometries_index_list_size;
|
||||
SimpleLogger().Write(logDEBUG) << "geometries_list_size: " << geometries_list_size;
|
||||
SimpleLogger().Write(logDEBUG) << "sizeof(checksum): " << sizeof(checksum);
|
||||
SimpleLogger().Write(logDEBUG) << "ram index file name: " << ram_index_file_name;
|
||||
}
|
||||
|
||||
uint64_t GetSizeOfLayout() const {
|
||||
uint64_t result =
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
||||
(timestamp_length * sizeof(char) ) +
|
||||
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
|
||||
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
|
||||
(r_search_tree_size * sizeof(RTreeNode) ) +
|
||||
sizeof(checksum) +
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
|
||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
|
||||
(timestamp_length * sizeof(char) ) +
|
||||
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
|
||||
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
|
||||
(r_search_tree_size * sizeof(RTreeNode) ) +
|
||||
(geometries_indicators/32 + 1) * sizeof(unsigned) +
|
||||
(geometries_index_list_size * sizeof(unsigned) ) +
|
||||
(geometries_list_size * sizeof(unsigned) ) +
|
||||
sizeof(checksum) +
|
||||
1024*sizeof(char);
|
||||
return result;
|
||||
}
|
||||
@@ -140,10 +153,10 @@ struct SharedDataLayout {
|
||||
(via_node_list_size * sizeof(NodeID) );
|
||||
return result;
|
||||
}
|
||||
uint64_t GetGraphEdgeListOffsett() const {
|
||||
uint64_t GetGraphEdgeListOffset() const {
|
||||
uint64_t result =
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) ;
|
||||
@@ -184,29 +197,79 @@ struct SharedDataLayout {
|
||||
}
|
||||
uint64_t GetRSearchTreeOffset() const {
|
||||
uint64_t result =
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
||||
(timestamp_length * sizeof(char) ) +
|
||||
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
|
||||
(turn_instruction_list_size * sizeof(TurnInstructions) );
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
|
||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
|
||||
(timestamp_length * sizeof(char) ) +
|
||||
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
|
||||
(turn_instruction_list_size * sizeof(TurnInstructionsClass));
|
||||
return result;
|
||||
}
|
||||
uint64_t GetGeometriesIndicatorOffset() const {
|
||||
uint64_t result =
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
|
||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
|
||||
(timestamp_length * sizeof(char) ) +
|
||||
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
|
||||
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
|
||||
(r_search_tree_size * sizeof(RTreeNode) );
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t GetGeometriesIndexListOffset() const
|
||||
{ uint64_t result =
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
|
||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
|
||||
(timestamp_length * sizeof(char) ) +
|
||||
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
|
||||
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
|
||||
(r_search_tree_size * sizeof(RTreeNode) ) +
|
||||
(geometries_indicators/32 + 1) * sizeof(unsigned);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t GetGeometryListOffset() const {
|
||||
uint64_t result =
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
|
||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
|
||||
(timestamp_length * sizeof(char) ) +
|
||||
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
|
||||
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
|
||||
(r_search_tree_size * sizeof(RTreeNode) ) +
|
||||
(geometries_indicators/32 + 1) * sizeof(unsigned) +
|
||||
(geometries_index_list_size * sizeof(unsigned) );
|
||||
return result;
|
||||
}
|
||||
uint64_t GetChecksumOffset() const {
|
||||
uint64_t result =
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
||||
(timestamp_length * sizeof(char) ) +
|
||||
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
|
||||
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
|
||||
(r_search_tree_size * sizeof(RTreeNode) );
|
||||
(name_index_list_size * sizeof(unsigned) ) +
|
||||
(name_char_list_size * sizeof(char) ) +
|
||||
(name_id_list_size * sizeof(unsigned) ) +
|
||||
(via_node_list_size * sizeof(NodeID) ) +
|
||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
|
||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
|
||||
(timestamp_length * sizeof(char) ) +
|
||||
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
|
||||
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
|
||||
(r_search_tree_size * sizeof(RTreeNode) ) +
|
||||
(geometries_indicators/32 + 1) * sizeof(unsigned) +
|
||||
(geometries_index_list_size * sizeof(unsigned) ) +
|
||||
(geometries_list_size * sizeof(unsigned) );
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace http {
|
||||
void Reply::setSize(const unsigned size) {
|
||||
BOOST_FOREACH ( Header& h, headers) {
|
||||
if("Content-Length" == h.name) {
|
||||
std::string sizeString;
|
||||
intToString(size,h.value);
|
||||
}
|
||||
}
|
||||
@@ -74,10 +73,10 @@ std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
|
||||
std::vector<boost::asio::const_buffer> buffers;
|
||||
buffers.push_back(ToBuffer(status));
|
||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
||||
Header& h = headers[i];
|
||||
buffers.push_back(boost::asio::buffer(h.name));
|
||||
Header& current_header = headers[i];
|
||||
buffers.push_back(boost::asio::buffer(current_header.name));
|
||||
buffers.push_back(boost::asio::buffer(seperators));
|
||||
buffers.push_back(boost::asio::buffer(h.value));
|
||||
buffers.push_back(boost::asio::buffer(current_header.value));
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
}
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
@@ -88,16 +87,16 @@ Reply Reply::StockReply(Reply::status_type status) {
|
||||
Reply rep;
|
||||
rep.status = status;
|
||||
rep.content.clear();
|
||||
rep.content.push_back( ToString(status) );
|
||||
rep.content.push_back(rep.ToString(status));
|
||||
rep.headers.resize(3);
|
||||
rep.headers[0].name = "Access-Control-Allow-Origin";
|
||||
rep.headers[0].value = "*";
|
||||
rep.headers[1].name = "Content-Length";
|
||||
|
||||
std::string s;
|
||||
intToString(rep.content.size(), s);
|
||||
std::string size_string;
|
||||
intToString(rep.content.size(), size_string);
|
||||
|
||||
rep.headers[1].value = s;
|
||||
rep.headers[1].value = size_string;
|
||||
rep.headers[2].name = "Content-Type";
|
||||
rep.headers[2].value = "text/html";
|
||||
return rep;
|
||||
|
||||
@@ -27,12 +27,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "APIGrammar.h"
|
||||
#include "RequestHandler.h"
|
||||
#include "Http/Request.h"
|
||||
|
||||
#include "../Library/OSRM.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
@@ -76,21 +78,15 @@ void RequestHandler::handle_request(const http::Request& req, http::Reply& rep){
|
||||
|
||||
if ( !result || (it != request.end()) ) {
|
||||
rep = http::Reply::StockReply(http::Reply::badRequest);
|
||||
rep.content.clear();
|
||||
const int position = std::distance(request.begin(), it);
|
||||
rep.content.push_back(
|
||||
"{\"status\":400,\"status_message\":\"Query string malformed close to position "
|
||||
);
|
||||
std::string tmp_position_string;
|
||||
intToString(position, tmp_position_string);
|
||||
rep.content.push_back(
|
||||
"Input seems to be malformed close to position "
|
||||
"<br><pre>"
|
||||
);
|
||||
rep.content.push_back( request );
|
||||
rep.content.push_back(tmp_position_string);
|
||||
rep.content.push_back("<br>");
|
||||
const unsigned end = std::distance(request.begin(), it);
|
||||
for(unsigned i = 0; i < end; ++i) {
|
||||
rep.content.push_back(" ");
|
||||
}
|
||||
rep.content.push_back("^<br></pre>");
|
||||
rep.content.push_back("\"}");
|
||||
} else {
|
||||
//parsing done, lets call the right plugin to handle the request
|
||||
BOOST_ASSERT_MSG(
|
||||
|
||||
@@ -28,10 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef REQUEST_HANDLER_H
|
||||
#define REQUEST_HANDLER_H
|
||||
|
||||
#include "Http/Request.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <string>
|
||||
@@ -41,6 +37,11 @@ struct APIGrammar;
|
||||
struct RouteParameters;
|
||||
class OSRM;
|
||||
|
||||
namespace http {
|
||||
class Reply;
|
||||
struct Request;
|
||||
}
|
||||
|
||||
class RequestHandler : private boost::noncopyable {
|
||||
|
||||
public:
|
||||
|
||||
+142
-112
@@ -38,11 +38,13 @@ boost::tuple<boost::tribool, char*> RequestParser::Parse(
|
||||
Request& req,
|
||||
char* begin,
|
||||
char* end,
|
||||
http::CompressionType * compressionType
|
||||
) {
|
||||
while (begin != end) {
|
||||
http::CompressionType * compressionType)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
boost::tribool result = consume(req, *begin++, compressionType);
|
||||
if (result || !result){
|
||||
if (result || !result)
|
||||
{
|
||||
return boost::make_tuple(result, begin);
|
||||
}
|
||||
}
|
||||
@@ -50,193 +52,216 @@ boost::tuple<boost::tribool, char*> RequestParser::Parse(
|
||||
return boost::make_tuple(result, begin);
|
||||
}
|
||||
|
||||
boost::tribool RequestParser::consume(
|
||||
Request& req, char input,
|
||||
http::CompressionType * compressionType
|
||||
) {
|
||||
switch (state_) {
|
||||
boost::tribool RequestParser::consume(Request& req, char input, http::CompressionType * compressionType)
|
||||
{
|
||||
switch (state_)
|
||||
{
|
||||
case method_start:
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input))
|
||||
{
|
||||
return false;
|
||||
} else {
|
||||
state_ = method;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
state_ = method;
|
||||
return boost::indeterminate;
|
||||
case method:
|
||||
if (input == ' ') {
|
||||
if (input == ' ')
|
||||
{
|
||||
state_ = uri;
|
||||
return boost::indeterminate;
|
||||
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||
return false;
|
||||
} else {
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return boost::indeterminate;
|
||||
case uri_start:
|
||||
if (isCTL(input)) {
|
||||
if (isCTL(input))
|
||||
{
|
||||
return false;
|
||||
} else {
|
||||
state_ = uri;
|
||||
req.uri.push_back(input);
|
||||
return boost::indeterminate;
|
||||
}
|
||||
state_ = uri;
|
||||
req.uri.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case uri:
|
||||
if (input == ' ') {
|
||||
if (input == ' ')
|
||||
{
|
||||
state_ = http_version_h;
|
||||
return boost::indeterminate;
|
||||
} else if (isCTL(input)) {
|
||||
return false;
|
||||
} else {
|
||||
req.uri.push_back(input);
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (isCTL(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
req.uri.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case http_version_h:
|
||||
if (input == 'H') {
|
||||
if (input == 'H')
|
||||
{
|
||||
state_ = http_version_t_1;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case http_version_t_1:
|
||||
if (input == 'T') {
|
||||
if (input == 'T')
|
||||
{
|
||||
state_ = http_version_t_2;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case http_version_t_2:
|
||||
if (input == 'T') {
|
||||
if (input == 'T')
|
||||
{
|
||||
state_ = http_version_p;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case http_version_p:
|
||||
if (input == 'P') {
|
||||
if (input == 'P')
|
||||
{
|
||||
state_ = http_version_slash;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case http_version_slash:
|
||||
if (input == '/') {
|
||||
if (input == '/')
|
||||
{
|
||||
state_ = http_version_major_start;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case http_version_major_start:
|
||||
if (isDigit(input)) {
|
||||
if (isDigit(input))
|
||||
{
|
||||
state_ = http_version_major;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case http_version_major:
|
||||
if (input == '.') {
|
||||
if (input == '.')
|
||||
{
|
||||
state_ = http_version_minor_start;
|
||||
return boost::indeterminate;
|
||||
} else if (isDigit(input)) {
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (isDigit(input))
|
||||
{
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case http_version_minor_start:
|
||||
if (isDigit(input)) {
|
||||
if (isDigit(input))
|
||||
{
|
||||
state_ = http_version_minor;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case http_version_minor:
|
||||
if (input == '\r') {
|
||||
if (input == '\r')
|
||||
{
|
||||
state_ = expecting_newline_1;
|
||||
return boost::indeterminate;
|
||||
} else if (isDigit(input)) {
|
||||
}
|
||||
if (isDigit(input))
|
||||
{
|
||||
return boost::indeterminate;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case expecting_newline_1:
|
||||
if (input == '\n') {
|
||||
if (input == '\n')
|
||||
{
|
||||
state_ = header_line_start;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case header_line_start:
|
||||
if(header.name == "Accept-Encoding") {
|
||||
if(header.name == "Accept-Encoding")
|
||||
{
|
||||
/* giving gzip precedence over deflate */
|
||||
if(header.value.find("deflate") != std::string::npos)
|
||||
if (header.value.find("deflate") != std::string::npos)
|
||||
{
|
||||
*compressionType = deflateRFC1951;
|
||||
if(header.value.find("gzip") != std::string::npos)
|
||||
}
|
||||
if (header.value.find("gzip") != std::string::npos)
|
||||
{
|
||||
*compressionType = gzipRFC1952;
|
||||
}
|
||||
}
|
||||
|
||||
if("Referer" == header.name)
|
||||
if ("Referer" == header.name)
|
||||
{
|
||||
req.referrer = header.value;
|
||||
}
|
||||
|
||||
if("User-Agent" == header.name)
|
||||
if ("User-Agent" == header.name)
|
||||
{
|
||||
req.agent = header.value;
|
||||
}
|
||||
|
||||
if (input == '\r') {
|
||||
if (input == '\r')
|
||||
{
|
||||
state_ = expecting_newline_3;
|
||||
return boost::indeterminate;
|
||||
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||
return false;
|
||||
} else {
|
||||
state_ = header_name;
|
||||
header.Clear();
|
||||
header.name.push_back(input);
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
state_ = header_name;
|
||||
header.Clear();
|
||||
header.name.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case header_lws:
|
||||
if (input == '\r') {
|
||||
if (input == '\r')
|
||||
{
|
||||
state_ = expecting_newline_2;
|
||||
return boost::indeterminate;
|
||||
} else if (input == ' ' || input == '\t') {
|
||||
}
|
||||
if (input == ' ' || input == '\t')
|
||||
{
|
||||
return boost::indeterminate;
|
||||
}
|
||||
else if (isCTL(input)) {
|
||||
if (isCTL(input)) {
|
||||
return false;
|
||||
} else {
|
||||
state_ = header_value;
|
||||
return boost::indeterminate;
|
||||
}
|
||||
state_ = header_value;
|
||||
return boost::indeterminate;
|
||||
case header_name:
|
||||
if (input == ':') {
|
||||
if (input == ':')
|
||||
{
|
||||
state_ = space_before_header_value;
|
||||
return boost::indeterminate;
|
||||
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||
return false;
|
||||
} else {
|
||||
header.name.push_back(input);
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (!isChar(input) || isCTL(input) || isTSpecial(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
header.name.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case space_before_header_value:
|
||||
if (input == ' ') {
|
||||
if (input == ' ')
|
||||
{
|
||||
state_ = header_value;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case header_value:
|
||||
if (input == '\r') {
|
||||
if (input == '\r')
|
||||
{
|
||||
state_ = expecting_newline_2;
|
||||
return boost::indeterminate;
|
||||
} else if (isCTL(input)) {
|
||||
return false;
|
||||
} else {
|
||||
header.value.push_back(input);
|
||||
return boost::indeterminate;
|
||||
}
|
||||
if (isCTL(input))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
header.value.push_back(input);
|
||||
return boost::indeterminate;
|
||||
case expecting_newline_2:
|
||||
if (input == '\n') {
|
||||
if (input == '\n')
|
||||
{
|
||||
state_ = header_line_start;
|
||||
return boost::indeterminate;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case expecting_newline_3:
|
||||
return (input == '\n');
|
||||
default:
|
||||
@@ -244,27 +269,32 @@ boost::tribool RequestParser::consume(
|
||||
}
|
||||
}
|
||||
|
||||
inline bool RequestParser::isChar(int c) {
|
||||
inline bool RequestParser::isChar(int c)
|
||||
{
|
||||
return c >= 0 && c <= 127;
|
||||
}
|
||||
|
||||
inline bool RequestParser::isCTL(int c) {
|
||||
inline bool RequestParser::isCTL(int c)
|
||||
{
|
||||
return (c >= 0 && c <= 31) || (c == 127);
|
||||
}
|
||||
|
||||
inline bool RequestParser::isTSpecial(int c) {
|
||||
switch (c) {
|
||||
case '(': case ')': case '<': case '>': case '@':
|
||||
case ',': case ';': case ':': case '\\': case '"':
|
||||
case '/': case '[': case ']': case '?': case '=':
|
||||
case '{': case '}': case ' ': case '\t':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
inline bool RequestParser::isTSpecial(int c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '(': case ')': case '<': case '>': case '@':
|
||||
case ',': case ';': case ':': case '\\': case '"':
|
||||
case '/': case '[': case ']': case '?': case '=':
|
||||
case '{': case '}': case ' ': case '\t':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool RequestParser::isDigit(int c) {
|
||||
inline bool RequestParser::isDigit(int c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
@@ -72,7 +73,7 @@ public:
|
||||
void Run() {
|
||||
std::vector<boost::shared_ptr<boost::thread> > threads;
|
||||
for (unsigned i = 0; i < threadPoolSize; ++i) {
|
||||
boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &ioService)));
|
||||
boost::shared_ptr<boost::thread> thread = boost::make_shared<boost::thread>(boost::bind(&boost::asio::io_service::run, &ioService));
|
||||
threads.push_back(thread);
|
||||
}
|
||||
for (unsigned i = 0; i < threads.size(); ++i)
|
||||
|
||||
+76
-84
@@ -46,99 +46,91 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
typedef QueryEdge::EdgeData EdgeData;
|
||||
typedef QueryEdge::EdgeData EdgeData;
|
||||
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
||||
|
||||
std::vector<NodeInfo> internal_to_external_node_map;
|
||||
std::vector<TurnRestriction> restrictions_vector;
|
||||
std::vector<NodeID> bollard_node_IDs_vector;
|
||||
std::vector<NodeID> traffic_light_node_IDs_vector;
|
||||
std::vector<NodeInfo> internal_to_external_node_map;
|
||||
std::vector<TurnRestriction> restrictions_vector;
|
||||
std::vector<NodeID> bollard_node_IDs_vector;
|
||||
std::vector<NodeID> traffic_light_node_IDs_vector;
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
if(argc < 3) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
|
||||
if (argc < 3)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
|
||||
return -1;
|
||||
}
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
"Using restrictions from file: " << argv[2];
|
||||
std::ifstream restriction_ifstream(argv[2], std::ios::binary);
|
||||
const UUID uuid_orig;
|
||||
UUID uuid_loaded;
|
||||
restriction_ifstream.read((char *) &uuid_loaded, sizeof(UUID));
|
||||
try
|
||||
{
|
||||
SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
|
||||
std::ifstream restriction_ifstream(argv[2], std::ios::binary);
|
||||
const UUID uuid_orig;
|
||||
UUID uuid_loaded;
|
||||
restriction_ifstream.read((char *)&uuid_loaded, sizeof(UUID));
|
||||
|
||||
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
argv[2] << " was prepared with a different build. "
|
||||
"Reprocess to get rid of this warning.";
|
||||
if (!uuid_loaded.TestGraphUtil(uuid_orig))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
if (!restriction_ifstream.good())
|
||||
{
|
||||
throw OSRMException("Could not access <osrm-restrictions> files");
|
||||
}
|
||||
uint32_t usable_restriction_count = 0;
|
||||
restriction_ifstream.read((char *)&usable_restriction_count, sizeof(uint32_t));
|
||||
restrictions_vector.resize(usable_restriction_count);
|
||||
|
||||
restriction_ifstream.read((char *)&(restrictions_vector[0]),
|
||||
usable_restriction_count * sizeof(TurnRestriction));
|
||||
restriction_ifstream.close();
|
||||
|
||||
std::ifstream input_stream;
|
||||
input_stream.open(argv[1], std::ifstream::in | std::ifstream::binary);
|
||||
|
||||
if (!input_stream.is_open())
|
||||
{
|
||||
throw OSRMException("Cannot open osrm file");
|
||||
}
|
||||
|
||||
std::vector<ImportEdge> edge_list;
|
||||
NodeID node_based_node_count = readBinaryOSRMGraphFromStream(
|
||||
input_stream, edge_list, bollard_node_IDs_vector, traffic_light_node_IDs_vector,
|
||||
&internal_to_external_node_map, restrictions_vector);
|
||||
input_stream.close();
|
||||
|
||||
BOOST_ASSERT_MSG(restrictions_vector.size() == usable_restriction_count,
|
||||
"size of restrictions_vector changed");
|
||||
|
||||
SimpleLogger().Write() << restrictions_vector.size() << " restrictions, "
|
||||
<< bollard_node_IDs_vector.size() << " bollard nodes, "
|
||||
<< traffic_light_node_IDs_vector.size() << " traffic lights";
|
||||
|
||||
/***
|
||||
* Building an edge-expanded graph from node-based input an turn
|
||||
* restrictions
|
||||
*/
|
||||
|
||||
SimpleLogger().Write() << "Starting SCC graph traversal";
|
||||
TarjanSCC *tarjan = new TarjanSCC(node_based_node_count, edge_list, bollard_node_IDs_vector,
|
||||
traffic_light_node_IDs_vector, restrictions_vector,
|
||||
internal_to_external_node_map);
|
||||
std::vector<ImportEdge>().swap(edge_list);
|
||||
|
||||
tarjan->Run();
|
||||
|
||||
std::vector<TurnRestriction>().swap(restrictions_vector);
|
||||
std::vector<NodeID>().swap(bollard_node_IDs_vector);
|
||||
std::vector<NodeID>().swap(traffic_light_node_IDs_vector);
|
||||
SimpleLogger().Write() << "finished component analysis";
|
||||
}
|
||||
|
||||
if(!restriction_ifstream.good()) {
|
||||
throw OSRMException("Could not access <osrm-restrictions> files");
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
}
|
||||
uint32_t usable_restriction_count = 0;
|
||||
restriction_ifstream.read(
|
||||
(char*)&usable_restriction_count,
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
restrictions_vector.resize(usable_restriction_count);
|
||||
|
||||
restriction_ifstream.read(
|
||||
(char *)&(restrictions_vector[0]),
|
||||
usable_restriction_count*sizeof(TurnRestriction)
|
||||
);
|
||||
restriction_ifstream.close();
|
||||
|
||||
std::ifstream input_stream;
|
||||
input_stream.open( argv[1], std::ifstream::in | std::ifstream::binary );
|
||||
|
||||
if (!input_stream.is_open()) {
|
||||
throw OSRMException("Cannot open osrm file");
|
||||
}
|
||||
|
||||
std::vector<ImportEdge> edge_list;
|
||||
NodeID node_based_node_count = readBinaryOSRMGraphFromStream(
|
||||
input_stream,
|
||||
edge_list,
|
||||
bollard_node_IDs_vector,
|
||||
traffic_light_node_IDs_vector,
|
||||
&internal_to_external_node_map,
|
||||
restrictions_vector
|
||||
);
|
||||
input_stream.close();
|
||||
|
||||
BOOST_ASSERT_MSG(
|
||||
restrictions_vector.size() == usable_restriction_count,
|
||||
"size of restrictions_vector changed"
|
||||
);
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
restrictions_vector.size() << " restrictions, " <<
|
||||
bollard_node_IDs_vector.size() << " bollard nodes, " <<
|
||||
traffic_light_node_IDs_vector.size() << " traffic lights";
|
||||
|
||||
/***
|
||||
* Building an edge-expanded graph from node-based input an turn restrictions
|
||||
*/
|
||||
|
||||
SimpleLogger().Write() << "Starting SCC graph traversal";
|
||||
TarjanSCC * tarjan = new TarjanSCC (
|
||||
node_based_node_count,
|
||||
edge_list,
|
||||
bollard_node_IDs_vector,
|
||||
traffic_light_node_IDs_vector,
|
||||
restrictions_vector,
|
||||
internal_to_external_node_map
|
||||
);
|
||||
std::vector<ImportEdge>().swap(edge_list);
|
||||
|
||||
tarjan->Run();
|
||||
|
||||
std::vector<TurnRestriction>().swap(restrictions_vector);
|
||||
std::vector<NodeID>().swap(bollard_node_IDs_vector);
|
||||
std::vector<NodeID>().swap(traffic_light_node_IDs_vector);
|
||||
SimpleLogger().Write() << "finished component analysis";
|
||||
return 0;
|
||||
}
|
||||
|
||||
+142
-163
@@ -48,45 +48,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
const unsigned number_of_elements = 268435456;
|
||||
|
||||
struct Statistics { double min, max, med, mean, dev; };
|
||||
struct Statistics
|
||||
{
|
||||
double min, max, med, mean, dev;
|
||||
};
|
||||
|
||||
void RunStatistics(std::vector<double> & timings_vector, Statistics & stats) {
|
||||
void RunStatistics(std::vector<double> &timings_vector, Statistics &stats)
|
||||
{
|
||||
std::sort(timings_vector.begin(), timings_vector.end());
|
||||
stats.min = timings_vector.front();
|
||||
stats.max = timings_vector.back();
|
||||
stats.med = timings_vector[timings_vector.size()/2];
|
||||
double primary_sum = std::accumulate(
|
||||
timings_vector.begin(),
|
||||
timings_vector.end(),
|
||||
0.0
|
||||
);
|
||||
stats.med = timings_vector[timings_vector.size() / 2];
|
||||
double primary_sum = std::accumulate(timings_vector.begin(), timings_vector.end(), 0.0);
|
||||
stats.mean = primary_sum / timings_vector.size();
|
||||
|
||||
double primary_sq_sum = std::inner_product( timings_vector.begin(),
|
||||
timings_vector.end(),
|
||||
timings_vector.begin(),
|
||||
0.0
|
||||
);
|
||||
stats.dev = std::sqrt(
|
||||
primary_sq_sum / timings_vector.size() - (stats.mean * stats.mean)
|
||||
);
|
||||
double primary_sq_sum = std::inner_product(
|
||||
timings_vector.begin(), timings_vector.end(), timings_vector.begin(), 0.0);
|
||||
stats.dev = std::sqrt(primary_sq_sum / timings_vector.size() - (stats.mean * stats.mean));
|
||||
}
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
||||
"compiled at " << __DATE__ << ", " __TIME__;
|
||||
SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION << ", "
|
||||
<< "compiled at " << __DATE__ << ", " __TIME__;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
SimpleLogger().Write() << "Not supported on FreeBSD";
|
||||
return 0;
|
||||
SimpleLogger().Write() << "Not supported on FreeBSD";
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if( 1 == argc ) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"usage: " << argv[0] << " /path/on/device";
|
||||
if (1 == argc)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " /path/on/device";
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -94,119 +89,105 @@ int main (int argc, char * argv[]) {
|
||||
test_path /= "osrm.tst";
|
||||
SimpleLogger().Write(logDEBUG) << "temporary file: " << test_path.string();
|
||||
|
||||
try {
|
||||
//create files for testing
|
||||
if( 2 == argc) {
|
||||
//create file to test
|
||||
if( boost::filesystem::exists(test_path) ) {
|
||||
try
|
||||
{
|
||||
// create files for testing
|
||||
if (2 == argc)
|
||||
{
|
||||
// create file to test
|
||||
if (boost::filesystem::exists(test_path))
|
||||
{
|
||||
throw OSRMException("Data file already exists");
|
||||
}
|
||||
|
||||
double time1, time2;
|
||||
int * random_array = new int[number_of_elements];
|
||||
std::generate (
|
||||
random_array,
|
||||
random_array+number_of_elements,
|
||||
std::rand
|
||||
);
|
||||
int *random_array = new int[number_of_elements];
|
||||
std::generate(random_array, random_array + number_of_elements, std::rand);
|
||||
#ifdef __APPLE__
|
||||
FILE * fd = fopen(test_path.string().c_str(), "w");
|
||||
FILE *fd = fopen(test_path.string().c_str(), "w");
|
||||
fcntl(fileno(fd), F_NOCACHE, 1);
|
||||
fcntl(fileno(fd), F_RDAHEAD, 0);
|
||||
time1 = get_timestamp();
|
||||
write(
|
||||
fileno(fd),
|
||||
(char*)random_array,
|
||||
number_of_elements*sizeof(unsigned)
|
||||
);
|
||||
write(fileno(fd), (char *)random_array, number_of_elements * sizeof(unsigned));
|
||||
time2 = get_timestamp();
|
||||
fclose(fd);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
int f = open(
|
||||
test_path.string().c_str(),
|
||||
O_CREAT|O_TRUNC|O_WRONLY|O_SYNC,
|
||||
S_IRWXU
|
||||
);
|
||||
int f =
|
||||
open(test_path.string().c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, S_IRWXU);
|
||||
time1 = get_timestamp();
|
||||
int ret = write(
|
||||
f,
|
||||
random_array,
|
||||
number_of_elements*sizeof(unsigned)
|
||||
);
|
||||
if(-1 == ret) {
|
||||
int ret = write(f, random_array, number_of_elements * sizeof(unsigned));
|
||||
if (-1 == ret)
|
||||
{
|
||||
throw OSRMException("could not write random data file");
|
||||
}
|
||||
time2 = get_timestamp();
|
||||
close(f);
|
||||
#endif
|
||||
delete[] random_array;
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"writing raw 1GB took " << (time2-time1)*1000 << "ms";
|
||||
SimpleLogger().Write() << "raw write performance: " <<
|
||||
std::setprecision(5) << std::fixed <<
|
||||
1024*1024/((time2-time1)*1000) << "MB/sec";
|
||||
SimpleLogger().Write(logDEBUG) << "writing raw 1GB took " << (time2 - time1) * 1000
|
||||
<< "ms";
|
||||
SimpleLogger().Write() << "raw write performance: " << std::setprecision(5)
|
||||
<< std::fixed << 1024 * 1024 / ((time2 - time1) * 1000)
|
||||
<< "MB/sec";
|
||||
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"finished creation of random data. Flush disk cache now!";
|
||||
|
||||
} else {
|
||||
SimpleLogger().Write(logDEBUG)
|
||||
<< "finished creation of random data. Flush disk cache now!";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//
|
||||
// Run Non-Cached I/O benchmarks
|
||||
//
|
||||
|
||||
if( !boost::filesystem::exists(test_path) ) {
|
||||
if (!boost::filesystem::exists(test_path))
|
||||
{
|
||||
throw OSRMException("data file does not exist");
|
||||
}
|
||||
|
||||
double time1, time2;
|
||||
//volatiles do not get optimized
|
||||
// volatiles do not get optimized
|
||||
Statistics stats;
|
||||
|
||||
#ifdef __APPLE__
|
||||
volatile unsigned single_block[1024];
|
||||
char * raw_array = new char[number_of_elements*sizeof(unsigned)];
|
||||
FILE * fd = fopen(test_path.string().c_str(), "r");
|
||||
char *raw_array = new char[number_of_elements * sizeof(unsigned)];
|
||||
FILE *fd = fopen(test_path.string().c_str(), "r");
|
||||
fcntl(fileno(fd), F_NOCACHE, 1);
|
||||
fcntl(fileno(fd), F_RDAHEAD, 0);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
char * single_block = (char*) memalign(
|
||||
512,
|
||||
1024*sizeof(unsigned)
|
||||
);
|
||||
char *single_block = (char *)memalign(512, 1024 * sizeof(unsigned));
|
||||
|
||||
int f = open(test_path.string().c_str(), O_RDONLY|O_DIRECT|O_SYNC);
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"opened, error: " << strerror(errno);
|
||||
char * raw_array = (char*) memalign(
|
||||
512,
|
||||
number_of_elements*sizeof(unsigned)
|
||||
);
|
||||
int f = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
|
||||
if (-1 == f)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
|
||||
return -1;
|
||||
}
|
||||
char *raw_array = (char *)memalign(512, number_of_elements * sizeof(unsigned));
|
||||
#endif
|
||||
time1 = get_timestamp();
|
||||
#ifdef __APPLE__
|
||||
read(fileno(fd), raw_array, number_of_elements*sizeof(unsigned));
|
||||
read(fileno(fd), raw_array, number_of_elements * sizeof(unsigned));
|
||||
close(fileno(fd));
|
||||
fd = fopen(test_path.string().c_str(), "r");
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
int ret = read(f, raw_array, number_of_elements*sizeof(unsigned));
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"read " << ret << " bytes, error: " << strerror(errno);
|
||||
int ret = read(f, raw_array, number_of_elements * sizeof(unsigned));
|
||||
SimpleLogger().Write(logDEBUG) << "read " << ret
|
||||
<< " bytes, error: " << strerror(errno);
|
||||
close(f);
|
||||
f = open(test_path.string().c_str(), O_RDONLY|O_DIRECT|O_SYNC);
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"opened, error: " << strerror(errno);
|
||||
f = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
|
||||
SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
|
||||
#endif
|
||||
time2 = get_timestamp();
|
||||
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"reading raw 1GB took " << (time2-time1)*1000 << "ms";
|
||||
SimpleLogger().Write() << "raw read performance: " <<
|
||||
std::setprecision(5) << std::fixed <<
|
||||
1024*1024/((time2-time1)*1000) << "MB/sec";
|
||||
SimpleLogger().Write(logDEBUG) << "reading raw 1GB took " << (time2 - time1) * 1000
|
||||
<< "ms";
|
||||
SimpleLogger().Write() << "raw read performance: " << std::setprecision(5) << std::fixed
|
||||
<< 1024 * 1024 / ((time2 - time1) * 1000) << "MB/sec";
|
||||
|
||||
std::vector<double> timing_results_raw_random;
|
||||
SimpleLogger().Write(logDEBUG) << "running 1000 random I/Os of 4KB";
|
||||
@@ -217,60 +198,59 @@ int main (int argc, char * argv[]) {
|
||||
#ifdef __linux__
|
||||
lseek(f, 0, SEEK_SET);
|
||||
#endif
|
||||
//make 1000 random access, time each I/O seperately
|
||||
unsigned number_of_blocks = (number_of_elements*sizeof(unsigned)-1)/4096;
|
||||
for(unsigned i = 0; i < 1000; ++i) {
|
||||
unsigned block_to_read = std::rand()%number_of_blocks;
|
||||
off_t current_offset = block_to_read*4096;
|
||||
// make 1000 random access, time each I/O seperately
|
||||
unsigned number_of_blocks = (number_of_elements * sizeof(unsigned) - 1) / 4096;
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
unsigned block_to_read = std::rand() % number_of_blocks;
|
||||
off_t current_offset = block_to_read * 4096;
|
||||
time1 = get_timestamp();
|
||||
#ifdef __APPLE__
|
||||
int ret1 = fseek(fd, current_offset, SEEK_SET);
|
||||
int ret2 = read(fileno(fd), (char*)&single_block[0], 4096);
|
||||
int ret2 = read(fileno(fd), (char *)&single_block[0], 4096);
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
int ret1 = 0;
|
||||
int ret2 = 0;
|
||||
int ret1 = 0;
|
||||
int ret2 = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
int ret1 = lseek(f, current_offset, SEEK_SET);
|
||||
int ret2 = read(f, (char*)single_block, 4096);
|
||||
int ret2 = read(f, (char *)single_block, 4096);
|
||||
#endif
|
||||
time2 = get_timestamp();
|
||||
if( ((off_t)-1) == ret1) {
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "seek error " << strerror(errno);
|
||||
if (((off_t) - 1) == ret1)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
|
||||
throw OSRMException("seek error");
|
||||
}
|
||||
if(-1 == ret2) {
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "read error " << strerror(errno);
|
||||
if (-1 == ret2)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
|
||||
throw OSRMException("read error");
|
||||
}
|
||||
timing_results_raw_random.push_back((time2-time1)*1000.);
|
||||
timing_results_raw_random.push_back((time2 - time1) * 1000.);
|
||||
}
|
||||
|
||||
// Do statistics
|
||||
SimpleLogger().Write(logDEBUG) << "running raw random I/O statistics";
|
||||
std::ofstream random_csv("random.csv", std::ios::trunc);
|
||||
for(unsigned i = 0; i < timing_results_raw_random.size(); ++i) {
|
||||
for (unsigned i = 0; i < timing_results_raw_random.size(); ++i)
|
||||
{
|
||||
random_csv << i << ", " << timing_results_raw_random[i] << std::endl;
|
||||
}
|
||||
random_csv.close();
|
||||
RunStatistics(timing_results_raw_random, stats);
|
||||
|
||||
SimpleLogger().Write() << "raw random I/O: " <<
|
||||
std::setprecision(5) << std::fixed <<
|
||||
"min: " << stats.min << "ms, " <<
|
||||
"mean: " << stats.mean << "ms, " <<
|
||||
"med: " << stats.med << "ms, " <<
|
||||
"max: " << stats.max << "ms, " <<
|
||||
"dev: " << stats.dev << "ms";
|
||||
SimpleLogger().Write() << "raw random I/O: " << std::setprecision(5) << std::fixed
|
||||
<< "min: " << stats.min << "ms, "
|
||||
<< "mean: " << stats.mean << "ms, "
|
||||
<< "med: " << stats.med << "ms, "
|
||||
<< "max: " << stats.max << "ms, "
|
||||
<< "dev: " << stats.dev << "ms";
|
||||
|
||||
std::vector<double> timing_results_raw_seq;
|
||||
#ifdef __APPLE__
|
||||
@@ -280,81 +260,80 @@ int main (int argc, char * argv[]) {
|
||||
lseek(f, 0, SEEK_SET);
|
||||
#endif
|
||||
|
||||
//read every 100th block
|
||||
for(
|
||||
unsigned i = 0;
|
||||
i < 1000;
|
||||
++i
|
||||
) {
|
||||
off_t current_offset = i*4096;
|
||||
// read every 100th block
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
off_t current_offset = i * 4096;
|
||||
time1 = get_timestamp();
|
||||
#ifdef __APPLE__
|
||||
#ifdef __APPLE__
|
||||
int ret1 = fseek(fd, current_offset, SEEK_SET);
|
||||
int ret2 = read(fileno(fd), (char*)&single_block, 4096);
|
||||
#endif
|
||||
int ret2 = read(fileno(fd), (char *)&single_block, 4096);
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
int ret1 = 0;
|
||||
int ret2 = 0;
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
int ret1 = 0;
|
||||
int ret2 = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef __linux__
|
||||
int ret1 = lseek(f, current_offset, SEEK_SET);
|
||||
|
||||
int ret2 = read(f, (char*)single_block, 4096);
|
||||
#endif
|
||||
int ret2 = read(f, (char *)single_block, 4096);
|
||||
#endif
|
||||
time2 = get_timestamp();
|
||||
if( ((off_t)-1) == ret1) {
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "seek error " << strerror(errno);
|
||||
if (((off_t) - 1) == ret1)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
|
||||
throw OSRMException("seek error");
|
||||
}
|
||||
if(-1 == ret2) {
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "read error " << strerror(errno);
|
||||
if (-1 == ret2)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
|
||||
throw OSRMException("read error");
|
||||
}
|
||||
timing_results_raw_seq.push_back((time2-time1)*1000.);
|
||||
timing_results_raw_seq.push_back((time2 - time1) * 1000.);
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
#ifdef __APPLE__
|
||||
fclose(fd);
|
||||
// free(single_element);
|
||||
free(raw_array);
|
||||
// free(single_block);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
// free(single_block);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
close(f);
|
||||
#endif
|
||||
//Do statistics
|
||||
#endif
|
||||
// Do statistics
|
||||
SimpleLogger().Write(logDEBUG) << "running sequential I/O statistics";
|
||||
//print simple statistics: min, max, median, variance
|
||||
// print simple statistics: min, max, median, variance
|
||||
std::ofstream seq_csv("sequential.csv", std::ios::trunc);
|
||||
for(unsigned i = 0; i < timing_results_raw_seq.size(); ++i) {
|
||||
for (unsigned i = 0; i < timing_results_raw_seq.size(); ++i)
|
||||
{
|
||||
seq_csv << i << ", " << timing_results_raw_seq[i] << std::endl;
|
||||
}
|
||||
seq_csv.close();
|
||||
RunStatistics(timing_results_raw_seq, stats);
|
||||
SimpleLogger().Write() << "raw sequential I/O: " <<
|
||||
std::setprecision(5) << std::fixed <<
|
||||
"min: " << stats.min << "ms, " <<
|
||||
"mean: " << stats.mean << "ms, " <<
|
||||
"med: " << stats.med << "ms, " <<
|
||||
"max: " << stats.max << "ms, " <<
|
||||
"dev: " << stats.dev << "ms";
|
||||
SimpleLogger().Write() << "raw sequential I/O: " << std::setprecision(5) << std::fixed
|
||||
<< "min: " << stats.min << "ms, "
|
||||
<< "mean: " << stats.mean << "ms, "
|
||||
<< "med: " << stats.med << "ms, "
|
||||
<< "max: " << stats.max << "ms, "
|
||||
<< "dev: " << stats.dev << "ms";
|
||||
|
||||
if( boost::filesystem::exists(test_path) ) {
|
||||
if (boost::filesystem::exists(test_path))
|
||||
{
|
||||
boost::filesystem::remove(test_path);
|
||||
SimpleLogger().Write(logDEBUG) << "removing temporary files";
|
||||
}
|
||||
}
|
||||
} catch ( const std::exception & e ) {
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
||||
SimpleLogger().Write(logWARNING) << "cleaning up, and exiting";
|
||||
if(boost::filesystem::exists(test_path)) {
|
||||
if (boost::filesystem::exists(test_path))
|
||||
{
|
||||
boost::filesystem::remove(test_path);
|
||||
SimpleLogger().Write(logWARNING) << "removing temporary files";
|
||||
}
|
||||
|
||||
@@ -33,13 +33,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
int main() {
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
SimpleLogger().Write() <<
|
||||
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
||||
"compiled at " << __DATE__ << ", " __TIME__;
|
||||
SimpleLogger().Write() << "Releasing all locks";
|
||||
SharedBarriers barrier;
|
||||
barrier.pending_update_mutex.unlock();
|
||||
barrier.query_mutex.unlock();
|
||||
barrier.update_mutex.unlock();
|
||||
try
|
||||
{
|
||||
SimpleLogger().Write() <<
|
||||
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
||||
"compiled at " << __DATE__ << ", " __TIME__;
|
||||
SimpleLogger().Write() << "Releasing all locks";
|
||||
SharedBarriers barrier;
|
||||
barrier.pending_update_mutex.unlock();
|
||||
barrier.query_mutex.unlock();
|
||||
barrier.update_mutex.unlock();
|
||||
}
|
||||
catch(const std::exception & e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+20
-20
@@ -105,11 +105,11 @@ inline bool GenerateDataStoreOptions(const int argc, const char * argv[], Server
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
|
||||
".edges file"
|
||||
)
|
||||
// (
|
||||
// "geometry",
|
||||
// boost::program_options::value<boost::filesystem::path>(&paths["geometries"]),
|
||||
// ".geometry file"
|
||||
// )
|
||||
(
|
||||
"geometry",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["geometry"]),
|
||||
".geometry file"
|
||||
)
|
||||
(
|
||||
"ramindex",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
|
||||
@@ -180,13 +180,13 @@ inline bool GenerateDataStoreOptions(const int argc, const char * argv[], Server
|
||||
boost::program_options::notify(option_variables);
|
||||
|
||||
const bool parameter_present =
|
||||
(paths.find("hsgrdata") != paths.end() && !paths.find("hsgrdata")->second.string().empty() ) ||
|
||||
(paths.find("hsgrdata") != paths.end() && !paths.find("hsgrdata" )->second.string().empty()) ||
|
||||
(paths.find("nodesdata") != paths.end() && !paths.find("nodesdata")->second.string().empty()) ||
|
||||
(paths.find("edgesdata") != paths.end() && !paths.find("edgesdata")->second.string().empty()) ||
|
||||
// (paths.find("geometry") != paths.end() && !paths.find("geometry")->second.string().empty())) ||
|
||||
(paths.find("ramindex") != paths.end() && !paths.find("ramindex")->second.string().empty()) ||
|
||||
(paths.find("geometry") != paths.end() && !paths.find("geometry" )->second.string().empty()) ||
|
||||
(paths.find("ramindex") != paths.end() && !paths.find("ramindex" )->second.string().empty()) ||
|
||||
(paths.find("fileindex") != paths.end() && !paths.find("fileindex")->second.string().empty()) ||
|
||||
(paths.find("timestamp") != paths.end() && !paths.find("timestamp")->second.string().empty()) ;
|
||||
(paths.find("timestamp") != paths.end() && !paths.find("timestamp")->second.string().empty());
|
||||
|
||||
if (parameter_present)
|
||||
{
|
||||
@@ -244,11 +244,11 @@ inline bool GenerateDataStoreOptions(const int argc, const char * argv[], Server
|
||||
path_iterator->second = base_string + ".edges";
|
||||
}
|
||||
|
||||
// path_iterator = paths.find("geometries");
|
||||
// if (path_iterator != paths.end())
|
||||
// {
|
||||
// path_iterator->second = base_string + ".geometry";
|
||||
// }
|
||||
path_iterator = paths.find("geometry");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".geometry";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("ramindex");
|
||||
if (path_iterator != paths.end())
|
||||
@@ -296,12 +296,12 @@ inline bool GenerateDataStoreOptions(const int argc, const char * argv[], Server
|
||||
}
|
||||
AssertPathExists(path_iterator->second);
|
||||
|
||||
// path_iterator = paths.find("geometries");
|
||||
// if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
// {
|
||||
// path_iterator->second = base_string + ".geometry";
|
||||
// }
|
||||
// AssertPathExists(path_iterator->second);
|
||||
path_iterator = paths.find("geometry");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
{
|
||||
throw OSRMException(".geometry file must be specified");
|
||||
}
|
||||
AssertPathExists(path_iterator->second);
|
||||
|
||||
path_iterator = paths.find("ramindex");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
|
||||
+9
-3
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
@@ -135,7 +136,7 @@ NodeID readBinaryOSRMGraphFromStream(
|
||||
short type;
|
||||
NodeID nameID;
|
||||
int length;
|
||||
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow;
|
||||
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, is_split;
|
||||
|
||||
for (EdgeID i=0; i<m; ++i) {
|
||||
input_stream.read((char*)&source, sizeof(unsigned));
|
||||
@@ -149,6 +150,7 @@ NodeID readBinaryOSRMGraphFromStream(
|
||||
input_stream.read((char*)&ignoreInGrid, sizeof(bool));
|
||||
input_stream.read((char*)&isAccessRestricted, sizeof(bool));
|
||||
input_stream.read((char*)&isContraFlow, sizeof(bool));
|
||||
input_stream.read((char*)&is_split, sizeof(bool));
|
||||
|
||||
BOOST_ASSERT_MSG(length > 0, "loaded null length edge" );
|
||||
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
|
||||
@@ -189,7 +191,7 @@ NodeID readBinaryOSRMGraphFromStream(
|
||||
std::swap(forward, backward);
|
||||
}
|
||||
|
||||
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow );
|
||||
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, is_split );
|
||||
edge_list.push_back(inputEdge);
|
||||
}
|
||||
std::sort(edge_list.begin(), edge_list.end());
|
||||
@@ -444,7 +446,10 @@ unsigned readHSGRFromStream(
|
||||
hsgr_input_stream.read( (char*) &number_of_nodes, sizeof(unsigned) );
|
||||
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
|
||||
hsgr_input_stream.read( (char*) &number_of_edges, sizeof(unsigned) );
|
||||
BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
|
||||
|
||||
SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes << ", number_of_edges: " << number_of_edges;
|
||||
|
||||
// BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
|
||||
node_list.resize(number_of_nodes + 1);
|
||||
hsgr_input_stream.read(
|
||||
(char*) &(node_list[0]),
|
||||
@@ -457,6 +462,7 @@ unsigned readHSGRFromStream(
|
||||
number_of_edges*sizeof(EdgeT)
|
||||
);
|
||||
hsgr_input_stream.close();
|
||||
|
||||
return number_of_nodes;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
class IniFile {
|
||||
public:
|
||||
IniFile(const char * config_filename);
|
||||
explicit IniFile(const char * config_filename);
|
||||
|
||||
std::string GetParameter(const std::string & key);
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
class OSRMException: public std::exception {
|
||||
public:
|
||||
OSRMException(const char * message) : message(message) {}
|
||||
OSRMException(const std::string & message) : message(message) {}
|
||||
explicit OSRMException(const char * message) : message(message) {}
|
||||
explicit OSRMException(const std::string & message) : message(message) {}
|
||||
virtual ~OSRMException() throw() {}
|
||||
private:
|
||||
virtual const char* what() const throw() {
|
||||
|
||||
@@ -110,6 +110,10 @@ inline unsigned GenerateServerProgramOptions(
|
||||
"edgesdata",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
|
||||
".edges file")
|
||||
(
|
||||
"geometry",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["geometries"]),
|
||||
".geometry file")
|
||||
(
|
||||
"ramindex",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
|
||||
@@ -252,6 +256,17 @@ inline unsigned GenerateServerProgramOptions(
|
||||
}
|
||||
|
||||
|
||||
path_iterator = paths.find("geometries");
|
||||
if(
|
||||
path_iterator != paths.end() &&
|
||||
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||
) {
|
||||
path_iterator->second = base_string + ".geometry";
|
||||
} else {
|
||||
throw OSRMException(base_string + ".geometry not found");
|
||||
}
|
||||
|
||||
|
||||
path_iterator = paths.find("ramindex");
|
||||
if(
|
||||
path_iterator != paths.end() &&
|
||||
|
||||
+21
-11
@@ -32,11 +32,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
|
||||
enum LogLevel { logINFO, logWARNING, logDEBUG };
|
||||
static boost::mutex logger_mutex;
|
||||
static boost::mutex logger_mutex;
|
||||
const char COL_RESET[] = "\x1b[0m";
|
||||
const char RED[] = "\x1b[31m";
|
||||
const char GREEN[] = "\x1b[32m";
|
||||
@@ -70,16 +72,20 @@ private:
|
||||
bool m_is_mute;
|
||||
};
|
||||
|
||||
class SimpleLogger {
|
||||
class SimpleLogger
|
||||
{
|
||||
public:
|
||||
SimpleLogger() : level(logINFO) { }
|
||||
|
||||
std::ostringstream& Write(LogLevel l = logINFO) {
|
||||
try {
|
||||
std::ostringstream& Write(LogLevel l = logINFO)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::mutex::scoped_lock lock(logger_mutex);
|
||||
level = l;
|
||||
os << "[";
|
||||
switch(level) {
|
||||
switch(level)
|
||||
{
|
||||
case logINFO:
|
||||
os << "info";
|
||||
break;
|
||||
@@ -96,22 +102,26 @@ public:
|
||||
break;
|
||||
}
|
||||
os << "] ";
|
||||
} catch (...) { }
|
||||
}
|
||||
catch (...) { }
|
||||
return os;
|
||||
}
|
||||
|
||||
virtual ~SimpleLogger() {
|
||||
if(!LogPolicy::GetInstance().IsMute()) {
|
||||
switch(level) {
|
||||
if(!LogPolicy::GetInstance().IsMute())
|
||||
{
|
||||
const bool is_terminal = isatty(fileno(stdout));
|
||||
switch(level)
|
||||
{
|
||||
case logINFO:
|
||||
std::cout << os.str() << COL_RESET << std::endl;
|
||||
std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
|
||||
break;
|
||||
case logWARNING:
|
||||
std::cerr << RED << os.str() << COL_RESET << std::endl;
|
||||
std::cerr << (is_terminal ? RED : "") << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
|
||||
break;
|
||||
case logDEBUG:
|
||||
#ifndef NDEBUG
|
||||
std::cout << YELLOW << os.str() << COL_RESET << std::endl;
|
||||
std::cout << (is_terminal ? YELLOW : "") << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -126,6 +126,40 @@ static inline uint64_t stringToInt64(const std::string& input) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// source: http://tinodidriksen.com/2011/05/28/cpp-convert-string-to-double-speed/
|
||||
static inline double StringToDouble(const char *p)
|
||||
{
|
||||
double r = 0.0;
|
||||
bool neg = false;
|
||||
if (*p == '-')
|
||||
{
|
||||
neg = true;
|
||||
++p;
|
||||
}
|
||||
while (*p >= '0' && *p <= '9')
|
||||
{
|
||||
r = (r*10.0) + (*p - '0');
|
||||
++p;
|
||||
}
|
||||
if (*p == '.')
|
||||
{
|
||||
double f = 0.0;
|
||||
int n = 0;
|
||||
++p;
|
||||
while (*p >= '0' && *p <= '9')
|
||||
{
|
||||
f = (f*10.0) + (*p - '0');
|
||||
++p;
|
||||
++n;
|
||||
}
|
||||
r += f / std::pow(10.0, n);
|
||||
}
|
||||
if (neg)
|
||||
{
|
||||
r = -r;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void doubleToString(const double value, std::string & output){
|
||||
output.clear();
|
||||
|
||||
+86
-25
@@ -44,22 +44,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <boost/integer.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/integer.hpp>
|
||||
#include <boost/iostreams/seek.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
int main( const int argc, const char * argv[] ) {
|
||||
|
||||
int main( const int argc, const char * argv[] )
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
SharedBarriers barrier;
|
||||
|
||||
#ifdef __linux__
|
||||
if( -1 == mlockall(MCL_CURRENT | MCL_FUTURE) ) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"Process " << argv[0] << " could not request RAM lock";
|
||||
}
|
||||
const bool lock_flags = MCL_CURRENT | MCL_FUTURE;
|
||||
if (-1 == mlockall(lock_flags))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Process " << argv[0] << " could not request RAM lock";
|
||||
}
|
||||
#endif
|
||||
|
||||
try {
|
||||
@@ -89,22 +92,25 @@ int main( const int argc, const char * argv[] ) {
|
||||
return 0;
|
||||
}
|
||||
if( server_paths.find("hsgrdata") == server_paths.end() ) {
|
||||
throw OSRMException("no hsgr file given in ini file");
|
||||
throw OSRMException("no hsgr file found");
|
||||
}
|
||||
if( server_paths.find("ramindex") == server_paths.end() ) {
|
||||
throw OSRMException("no ram index file given in ini file");
|
||||
throw OSRMException("no ram index file found");
|
||||
}
|
||||
if( server_paths.find("fileindex") == server_paths.end() ) {
|
||||
throw OSRMException("no leaf index file given in ini file");
|
||||
throw OSRMException("no leaf index file found");
|
||||
}
|
||||
if( server_paths.find("nodesdata") == server_paths.end() ) {
|
||||
throw OSRMException("no nodes file given in ini file");
|
||||
throw OSRMException("no nodes file found");
|
||||
}
|
||||
if( server_paths.find("edgesdata") == server_paths.end() ) {
|
||||
throw OSRMException("no edges file given in ini file");
|
||||
throw OSRMException("no edges file found");
|
||||
}
|
||||
if( server_paths.find("namesdata") == server_paths.end() ) {
|
||||
throw OSRMException("no names file given in ini file");
|
||||
throw OSRMException("no names file found");
|
||||
}
|
||||
if( server_paths.find("geometry") == server_paths.end() ) {
|
||||
throw OSRMException("no geometry file found");
|
||||
}
|
||||
|
||||
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
|
||||
@@ -136,7 +142,10 @@ int main( const int argc, const char * argv[] ) {
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path & names_data_path = paths_iterator->second;
|
||||
|
||||
paths_iterator = server_paths.find("geometry");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path & geometries_data_path = paths_iterator->second;
|
||||
|
||||
// get the shared memory segment to use
|
||||
bool use_first_segment = SharedMemory::RegionExists( LAYOUT_2 );
|
||||
@@ -163,7 +172,6 @@ int main( const int argc, const char * argv[] ) {
|
||||
shared_layout_ptr->ram_index_file_name[end_of_string_index] = '\0';
|
||||
|
||||
// collect number of elements to store in shared memory object
|
||||
SimpleLogger().Write(logDEBUG) << "Collecting files sizes";
|
||||
SimpleLogger().Write() << "load names from: " << names_data_path;
|
||||
// number of entries in name index
|
||||
boost::filesystem::ifstream name_stream(
|
||||
@@ -192,6 +200,7 @@ int main( const int argc, const char * argv[] ) {
|
||||
shared_layout_ptr->via_node_list_size = number_of_original_edges;
|
||||
shared_layout_ptr->name_id_list_size = number_of_original_edges;
|
||||
shared_layout_ptr->turn_instruction_list_size = number_of_original_edges;
|
||||
shared_layout_ptr->geometries_indicators = number_of_original_edges;
|
||||
|
||||
boost::filesystem::ifstream hsgr_input_stream(
|
||||
hsgr_path,
|
||||
@@ -200,13 +209,15 @@ int main( const int argc, const char * argv[] ) {
|
||||
|
||||
UUID uuid_loaded, uuid_orig;
|
||||
hsgr_input_stream.read((char *)&uuid_loaded, sizeof(UUID));
|
||||
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
".hsgr was prepared with different build. "
|
||||
"Reprocess to get rid of this warning.";
|
||||
} else {
|
||||
if (uuid_loaded.TestGraphUtil(uuid_orig))
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "UUID checked out ok";
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build. "
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
// load checksum
|
||||
unsigned checksum = 0;
|
||||
@@ -274,8 +285,21 @@ int main( const int argc, const char * argv[] ) {
|
||||
shared_layout_ptr->coordinate_list_size = coordinate_list_size;
|
||||
|
||||
|
||||
// allocate shared memory block
|
||||
// load geometries sizes
|
||||
std::ifstream geometry_input_stream(
|
||||
geometries_data_path.c_str(),
|
||||
std::ios::binary
|
||||
);
|
||||
unsigned number_of_geometries_indices = 0;
|
||||
unsigned number_of_compressed_geometries = 0;
|
||||
|
||||
geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned));
|
||||
shared_layout_ptr->geometries_index_list_size = number_of_geometries_indices;
|
||||
boost::iostreams::seek(geometry_input_stream, number_of_geometries_indices*sizeof(unsigned), BOOST_IOS::cur);
|
||||
geometry_input_stream.read( (char *)&number_of_compressed_geometries, sizeof(unsigned));
|
||||
shared_layout_ptr->geometries_list_size = number_of_compressed_geometries;
|
||||
|
||||
// allocate shared memory block
|
||||
SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout() << " bytes";
|
||||
SharedMemory * shared_memory = SharedMemoryFactory::Get(
|
||||
DATA,
|
||||
@@ -285,11 +309,9 @@ int main( const int argc, const char * argv[] ) {
|
||||
|
||||
// read actual data into shared memory object //
|
||||
// Loading street names
|
||||
// SimpleLogger().Write() << "Loading names index and chars from: " << names_data_path.string();
|
||||
unsigned * name_index_ptr = (unsigned*)(
|
||||
shared_memory_ptr + shared_layout_ptr->GetNameIndexOffset()
|
||||
);
|
||||
// SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_index_list_size*sizeof(unsigned);
|
||||
|
||||
name_stream.read(
|
||||
(char*)name_index_ptr,
|
||||
@@ -316,9 +338,12 @@ int main( const int argc, const char * argv[] ) {
|
||||
shared_memory_ptr + shared_layout_ptr->GetTurnInstructionListOffset()
|
||||
);
|
||||
|
||||
unsigned * geometries_indicator_ptr = (unsigned *)(
|
||||
shared_memory_ptr + shared_layout_ptr->GetGeometriesIndicatorOffset()
|
||||
);
|
||||
|
||||
OriginalEdgeData current_edge_data;
|
||||
for(unsigned i = 0; i < number_of_original_edges; ++i) {
|
||||
// SimpleLogger().Write() << i << "/" << number_of_edges;
|
||||
edges_input_stream.read(
|
||||
(char*)&(current_edge_data),
|
||||
sizeof(OriginalEdgeData)
|
||||
@@ -326,9 +351,43 @@ int main( const int argc, const char * argv[] ) {
|
||||
via_node_ptr[i] = current_edge_data.via_node;
|
||||
name_id_ptr[i] = current_edge_data.name_id;
|
||||
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
|
||||
|
||||
const unsigned bucket = i / 32;
|
||||
const unsigned offset = i % 32;
|
||||
unsigned value = ((0 == offset) ? 0 : geometries_indicator_ptr[bucket]);
|
||||
if (current_edge_data.compressed_geometry)
|
||||
{
|
||||
geometries_indicator_ptr[bucket] = (value | (1 << offset));
|
||||
}
|
||||
}
|
||||
edges_input_stream.close();
|
||||
|
||||
// load compressed geometry
|
||||
unsigned temporary_value;
|
||||
unsigned * geometries_index_ptr = (unsigned *)(
|
||||
shared_memory_ptr + shared_layout_ptr->GetGeometriesIndexListOffset()
|
||||
);
|
||||
geometry_input_stream.seekg(0, geometry_input_stream.beg);
|
||||
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
|
||||
BOOST_ASSERT(temporary_value == shared_layout_ptr->geometries_index_list_size);
|
||||
|
||||
geometry_input_stream.read(
|
||||
(char *)geometries_index_ptr,
|
||||
shared_layout_ptr->geometries_index_list_size*sizeof(unsigned)
|
||||
);
|
||||
|
||||
unsigned * geometries_list_ptr = (unsigned *)(
|
||||
shared_memory_ptr + shared_layout_ptr->GetGeometryListOffset()
|
||||
);
|
||||
|
||||
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
|
||||
BOOST_ASSERT(temporary_value == shared_layout_ptr->geometries_list_size);
|
||||
|
||||
geometry_input_stream.read(
|
||||
(char *)geometries_list_ptr,
|
||||
shared_layout_ptr->geometries_list_size*sizeof(unsigned)
|
||||
);
|
||||
|
||||
// Loading list of coordinates
|
||||
FixedPointCoordinate * coordinates_ptr = (FixedPointCoordinate *)(
|
||||
shared_memory_ptr + shared_layout_ptr->GetCoordinateListOffset()
|
||||
@@ -370,7 +429,7 @@ int main( const int argc, const char * argv[] ) {
|
||||
|
||||
// load the edges of the search graph
|
||||
QueryGraph::_StrEdge * graph_edge_list_ptr = (QueryGraph::_StrEdge *)(
|
||||
shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffsett()
|
||||
shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffset()
|
||||
);
|
||||
hsgr_input_stream.read(
|
||||
(char*) graph_edge_list_ptr,
|
||||
@@ -421,6 +480,8 @@ int main( const int argc, const char * argv[] ) {
|
||||
}
|
||||
}
|
||||
SimpleLogger().Write() << "all data loaded";
|
||||
|
||||
shared_layout_ptr->PrintInformation();
|
||||
} catch(const std::exception & e) {
|
||||
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
||||
}
|
||||
|
||||
+76
-46
@@ -43,6 +43,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
@@ -99,12 +101,14 @@ int main (int argc, char *argv[]) {
|
||||
boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
|
||||
options(cmdline_options).positional(positional_options).run(), option_variables);
|
||||
|
||||
if(option_variables.count("version")) {
|
||||
if(option_variables.count("version"))
|
||||
{
|
||||
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(option_variables.count("help")) {
|
||||
if(option_variables.count("help"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return 0;
|
||||
}
|
||||
@@ -112,24 +116,38 @@ int main (int argc, char *argv[]) {
|
||||
boost::program_options::notify(option_variables);
|
||||
|
||||
// parse config file
|
||||
if(boost::filesystem::is_regular_file(config_file_path)) {
|
||||
SimpleLogger().Write() << "Reading options from: " << config_file_path.c_str();
|
||||
if(boost::filesystem::is_regular_file(config_file_path))
|
||||
{
|
||||
SimpleLogger().Write() << "Reading options from: " << config_file_path.string();
|
||||
std::string config_str;
|
||||
PrepareConfigFile( config_file_path.c_str(), config_str );
|
||||
PrepareConfigFile(config_file_path.c_str(), config_str);
|
||||
std::stringstream config_stream( config_str );
|
||||
boost::program_options::store(parse_config_file(config_stream, config_file_options), option_variables);
|
||||
boost::program_options::notify(option_variables);
|
||||
}
|
||||
|
||||
if(!option_variables.count("input")) {
|
||||
SimpleLogger().Write(logWARNING) << "No input file specified";
|
||||
if(!option_variables.count("input"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(1 > requested_num_threads) {
|
||||
if(1 > requested_num_threads)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!boost::filesystem::is_regular_file(input_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Input file " << input_path.string() << " not found!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!boost::filesystem::is_regular_file(profile_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string() << " not found!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "Input file: " << input_path.filename().string();
|
||||
@@ -139,51 +157,65 @@ int main (int argc, char *argv[]) {
|
||||
/*** Setup Scripting Environment ***/
|
||||
ScriptingEnvironment scriptingEnvironment(profile_path.c_str());
|
||||
|
||||
omp_set_num_threads( std::min( omp_get_num_procs(), requested_num_threads) );
|
||||
omp_set_num_threads(std::min(omp_get_num_procs(), requested_num_threads));
|
||||
|
||||
bool file_has_pbf_format(false);
|
||||
std::string output_file_name(input_path.c_str());
|
||||
std::string restrictionsFileName(input_path.c_str());
|
||||
std::string output_file_name = input_path.string();
|
||||
std::string restrictionsFileName = input_path.string();
|
||||
std::string::size_type pos = output_file_name.find(".osm.bz2");
|
||||
if(pos==std::string::npos) {
|
||||
if(pos==std::string::npos)
|
||||
{
|
||||
pos = output_file_name.find(".osm.pbf");
|
||||
if(pos!=std::string::npos) {
|
||||
if (pos!=std::string::npos)
|
||||
{
|
||||
file_has_pbf_format = true;
|
||||
}
|
||||
}
|
||||
if(pos==std::string::npos) {
|
||||
if (pos==std::string::npos)
|
||||
{
|
||||
pos = output_file_name.find(".pbf");
|
||||
if(pos!=std::string::npos) {
|
||||
if (pos!=std::string::npos)
|
||||
{
|
||||
file_has_pbf_format = true;
|
||||
}
|
||||
}
|
||||
if(pos!=std::string::npos) {
|
||||
output_file_name.replace(pos, 8, ".osrm");
|
||||
restrictionsFileName.replace(pos, 8, ".osrm.restrictions");
|
||||
} else {
|
||||
pos=output_file_name.find(".osm");
|
||||
if(pos!=std::string::npos) {
|
||||
output_file_name.replace(pos, 5, ".osrm");
|
||||
restrictionsFileName.replace(pos, 5, ".osrm.restrictions");
|
||||
} else {
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
pos = output_file_name.find(".osm");
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
output_file_name.append(".osrm");
|
||||
restrictionsFileName.append(".osrm.restrictions");
|
||||
}
|
||||
else
|
||||
{
|
||||
output_file_name.replace(pos, 5, ".osrm");
|
||||
restrictionsFileName.replace(pos, 5, ".osrm.restrictions");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
output_file_name.replace(pos, 8, ".osrm");
|
||||
restrictionsFileName.replace(pos, 8, ".osrm.restrictions");
|
||||
}
|
||||
|
||||
StringMap stringMap;
|
||||
boost::unordered_map<std::string, NodeID> stringMap;
|
||||
ExtractionContainers externalMemory;
|
||||
|
||||
stringMap[""] = 0;
|
||||
extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap);
|
||||
BaseParser* parser;
|
||||
if(file_has_pbf_format) {
|
||||
if(file_has_pbf_format)
|
||||
{
|
||||
parser = new PBFParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
parser = new XMLParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
|
||||
}
|
||||
|
||||
if(!parser->ReadHeader()) {
|
||||
if(!parser->ReadHeader())
|
||||
{
|
||||
throw OSRMException("Parser not initialized!");
|
||||
}
|
||||
SimpleLogger().Write() << "Parsing in progress..";
|
||||
@@ -193,9 +225,10 @@ int main (int argc, char *argv[]) {
|
||||
(get_timestamp() - parsing_start_time) <<
|
||||
" seconds";
|
||||
|
||||
if( externalMemory.all_edges_list.empty() ) {
|
||||
if (externalMemory.all_edges_list.empty())
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
externalMemory.PrepareData(output_file_name, restrictionsFileName);
|
||||
@@ -203,22 +236,19 @@ int main (int argc, char *argv[]) {
|
||||
delete parser;
|
||||
delete extractCallBacks;
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
"extraction finished after " << get_timestamp() - startup_time <<
|
||||
"s";
|
||||
SimpleLogger().Write() << "extraction finished after " << get_timestamp() - startup_time << "s";
|
||||
SimpleLogger().Write() << "To prepare the data for routing, run: " << "./osrm-prepare " << output_file_name << std::endl;
|
||||
|
||||
SimpleLogger().Write() << "To prepare the data for routing, run: "
|
||||
<< "./osrm-prepare " << output_file_name << std::endl;
|
||||
|
||||
} catch(boost::program_options::too_many_positional_options_error& e) {
|
||||
}
|
||||
catch(boost::program_options::too_many_positional_options_error& e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
|
||||
return -1;
|
||||
} catch(boost::program_options::error& e) {
|
||||
SimpleLogger().Write(logWARNING) << e.what();
|
||||
return -1;
|
||||
} catch(std::exception & e) {
|
||||
SimpleLogger().Write(logWARNING) << "Unhandled exception: " << e.what();
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
catch(std::exception & e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Exception occured: " << e.what();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ When a max speed is set, osrm will use 2/3 of that as the actual speed.
|
||||
| bc | trunk | 60 |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | speed |
|
||||
| a | b | ab | 85 km/h |
|
||||
| b | c | bc | 40 km/h |
|
||||
| from | to | route | speed |
|
||||
| a | b | ab | 85 km/h |
|
||||
| b | c | bc | 40 km/h +- 1 |
|
||||
|
||||
Scenario: Car - Do not ignore maxspeed when higher than way speed
|
||||
Given the node map
|
||||
@@ -30,22 +30,22 @@ When a max speed is set, osrm will use 2/3 of that as the actual speed.
|
||||
| bc | residential | 90 |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | speed |
|
||||
| a | b | ab | 25 km/h |
|
||||
| b | c | bc | 60 km/h |
|
||||
| from | to | route | speed |
|
||||
| a | b | ab | 25 km/h |
|
||||
| b | c | bc | 60 km/h +- 1 |
|
||||
|
||||
Scenario: Car - Forward/backward maxspeed
|
||||
Given a grid size of 100 meters
|
||||
|
||||
Then routability should be
|
||||
| highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw |
|
||||
| primary | | | | 65 km/h | 65 km/h |
|
||||
| primary | 60 | | | 40 km/h | 40 km/h |
|
||||
| primary | | 60 | | 40 km/h | 65 km/h |
|
||||
| primary | | | 60 | 65 km/h | 40 km/h |
|
||||
| primary | 15 | 60 | | 40 km/h | 10 km/h |
|
||||
| primary | 15 | | 60 | 10 km/h | 40 km/h |
|
||||
| primary | 15 | 30 | 60 | 20 km/h | 40 km/h |
|
||||
| highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw |
|
||||
| primary | | | | 65 km/h | 65 km/h |
|
||||
| primary | 60 | | | 40 km/h | 40 km/h |
|
||||
| primary | | 60 | | 40 km/h | 65 km/h |
|
||||
| primary | | | 60 | 65 km/h | 40 km/h |
|
||||
| primary | 15 | 60 | | 40 km/h | 10 km/h +- 1 |
|
||||
| primary | 15 | | 60 | 10 km/h +- 1| 40 km/h |
|
||||
| primary | 15 | 30 | 60 | 20 km/h | 40 km/h |
|
||||
|
||||
Scenario: Car - Maxspeed should not allow routing on unroutable ways
|
||||
Then routability should be
|
||||
@@ -62,4 +62,4 @@ When a max speed is set, osrm will use 2/3 of that as the actual speed.
|
||||
| runway | | | | | | |
|
||||
| runway | | | 100 | | | |
|
||||
| runway | | | | 100 | | |
|
||||
| runway | | | | | 100 | |
|
||||
| runway | | | | | 100 | |
|
||||
|
||||
+17
-17
@@ -1,24 +1,24 @@
|
||||
@routing @car @speed
|
||||
@routing @car @speed
|
||||
Feature: Car - speeds
|
||||
|
||||
Background:
|
||||
Given the profile "car"
|
||||
And a grid size of 1000 meters
|
||||
|
||||
|
||||
Scenario: Car - speed of various way types
|
||||
Then routability should be
|
||||
| highway | oneway | bothw |
|
||||
| motorway | no | 90 km/h |
|
||||
| motorway_link | no | 75 km/h |
|
||||
| trunk | no | 85 km/h |
|
||||
| trunk_link | no | 70 km/h |
|
||||
| primary | no | 65 km/h |
|
||||
| primary_link | no | 60 km/h |
|
||||
| secondary | no | 55 km/h |
|
||||
| secondary_link | no | 50 km/h |
|
||||
| tertiary | no | 40 km/h |
|
||||
| tertiary_link | no | 30 km/h |
|
||||
| unclassified | no | 25 km/h |
|
||||
| residential | no | 25 km/h |
|
||||
| living_street | no | 10 km/h |
|
||||
| service | no | 15 km/h |
|
||||
| highway | oneway | bothw |
|
||||
| motorway | no | 90 km/h |
|
||||
| motorway_link | no | 75 km/h |
|
||||
| trunk | no | 85 km/h +- 1 |
|
||||
| trunk_link | no | 70 km/h +- 1 |
|
||||
| primary | no | 65 km/h +- 1 |
|
||||
| primary_link | no | 60 km/h |
|
||||
| secondary | no | 55 km/h +- 1 |
|
||||
| secondary_link | no | 50 km/h |
|
||||
| tertiary | no | 40 km/h |
|
||||
| tertiary_link | no | 30 km/h |
|
||||
| unclassified | no | 25 km/h |
|
||||
| residential | no | 25 km/h |
|
||||
| living_street | no | 10 km/h |
|
||||
| service | no | 15 km/h |
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
@extract @options @files
|
||||
Feature: osrm-extract command line options: files
|
||||
# expansions:
|
||||
# {base} => path to current input file
|
||||
# {profile} => path to current profile script
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
And the node map
|
||||
| a | b |
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
And the data has been saved to disk
|
||||
|
||||
Scenario: osrm-extract - Passing base file
|
||||
When I run "osrm-extract {base}.osm --profile {profile}"
|
||||
Then stderr should be empty
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-extract - Order of options should not matter
|
||||
When I run "osrm-extract --profile {profile} {base}.osm"
|
||||
Then stderr should be empty
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-extract - Missing input file
|
||||
When I run "osrm-extract over-the-rainbow.osrm --profile {profile}"
|
||||
And stderr should contain "over-the-rainbow.osrm"
|
||||
And stderr should contain "not found"
|
||||
And it should exit with code 1
|
||||
@@ -0,0 +1,47 @@
|
||||
@extract @options @help
|
||||
Feature: osrm-extract command line options: help
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: osrm-extract - Help should be shown when no options are passed
|
||||
When I run "osrm-extract"
|
||||
Then stderr should be empty
|
||||
And stdout should contain "osrm-extract <input.osm/.osm.bz2/.osm.pbf> [options]:"
|
||||
And stdout should contain "Options:"
|
||||
And stdout should contain "--version"
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "--config"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--profile"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain 12 lines
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-extract - Help, short
|
||||
When I run "osrm-extract -h"
|
||||
Then stderr should be empty
|
||||
And stdout should contain "osrm-extract <input.osm/.osm.bz2/.osm.pbf> [options]:"
|
||||
And stdout should contain "Options:"
|
||||
And stdout should contain "--version"
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "--config"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--profile"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain 12 lines
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-extract - Help, long
|
||||
When I run "osrm-extract --help"
|
||||
Then stderr should be empty
|
||||
And stdout should contain "osrm-extract <input.osm/.osm.bz2/.osm.pbf> [options]:"
|
||||
And stdout should contain "Options:"
|
||||
And stdout should contain "--version"
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "--config"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--profile"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain 12 lines
|
||||
And it should exit with code 0
|
||||
@@ -0,0 +1,12 @@
|
||||
@extract @options @invalid
|
||||
Feature: osrm-extract command line options: invalid options
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: osrm-extract - Non-existing option
|
||||
When I run "osrm-extract --fly-me-to-the-moon"
|
||||
Then stdout should be empty
|
||||
And stderr should contain "option"
|
||||
And stderr should contain "fly-me-to-the-moon"
|
||||
And it should exit with code 1
|
||||
@@ -0,0 +1,22 @@
|
||||
@extract @options @version
|
||||
Feature: osrm-extract command line options: version
|
||||
# the regex will match these two formats:
|
||||
# v0.3.7.0 # this is the normal format when you build from a git clone
|
||||
# -128-NOTFOUND # if you build from a shallow clone (used on Travis)
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: osrm-extract - Version, short
|
||||
When I run "osrm-extract --v"
|
||||
Then stderr should be empty
|
||||
And stdout should contain 1 line
|
||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-extract - Version, long
|
||||
When I run "osrm-extract --version"
|
||||
Then stderr should be empty
|
||||
And stdout should contain 1 line
|
||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||
And it should exit with code 0
|
||||
@@ -0,0 +1,30 @@
|
||||
@prepare @options @files
|
||||
Feature: osrm-prepare command line options: files
|
||||
# expansions:
|
||||
# {base} => path to current input file
|
||||
# {profile} => path to current profile script
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
And the node map
|
||||
| a | b |
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
And the data has been extracted
|
||||
|
||||
Scenario: osrm-prepare - Passing base file
|
||||
When I run "osrm-prepare {base}.osrm --profile {profile}"
|
||||
Then stderr should be empty
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-prepare - Order of options should not matter
|
||||
When I run "osrm-prepare --profile {profile} {base}.osrm"
|
||||
Then stderr should be empty
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-prepare - Missing input file
|
||||
When I run "osrm-prepare over-the-rainbow.osrm --profile {profile}"
|
||||
And stderr should contain "over-the-rainbow.osrm"
|
||||
And stderr should contain "not found"
|
||||
And it should exit with code 1
|
||||
@@ -0,0 +1,50 @@
|
||||
@prepare @options @help
|
||||
Feature: osrm-prepare command line options: help
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: osrm-prepare - Help should be shown when no options are passed
|
||||
When I run "osrm-prepare"
|
||||
Then stderr should be empty
|
||||
And stdout should contain "osrm-prepare <input.osrm> [options]:"
|
||||
And stdout should contain "Options:"
|
||||
And stdout should contain "--version"
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "--config"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--restrictions"
|
||||
And stdout should contain "--profile"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain 15 lines
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-prepare - Help, short
|
||||
When I run "osrm-prepare -h"
|
||||
Then stderr should be empty
|
||||
And stdout should contain "osrm-prepare <input.osrm> [options]:"
|
||||
And stdout should contain "Options:"
|
||||
And stdout should contain "--version"
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "--config"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--restrictions"
|
||||
And stdout should contain "--profile"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain 15 lines
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-prepare - Help, long
|
||||
When I run "osrm-prepare --help"
|
||||
Then stderr should be empty
|
||||
And stdout should contain "osrm-prepare <input.osrm> [options]:"
|
||||
And stdout should contain "Options:"
|
||||
And stdout should contain "--version"
|
||||
And stdout should contain "--help"
|
||||
And stdout should contain "--config"
|
||||
And stdout should contain "Configuration:"
|
||||
And stdout should contain "--restrictions"
|
||||
And stdout should contain "--profile"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain 15 lines
|
||||
And it should exit with code 0
|
||||
@@ -0,0 +1,12 @@
|
||||
@prepare @options @invalid
|
||||
Feature: osrm-prepare command line options: invalid options
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: osrm-prepare - Non-existing option
|
||||
When I run "osrm-prepare --fly-me-to-the-moon"
|
||||
Then stdout should be empty
|
||||
And stderr should contain "option"
|
||||
And stderr should contain "fly-me-to-the-moon"
|
||||
And it should exit with code 1
|
||||
@@ -0,0 +1,22 @@
|
||||
@prepare @options @version
|
||||
Feature: osrm-prepare command line options: version
|
||||
# the regex will match these two formats:
|
||||
# v0.3.7.0 # this is the normal format when you build from a git clone
|
||||
# -128-NOTFOUND # if you build from a shallow clone (used on Travis)
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: osrm-prepare - Version, short
|
||||
When I run "osrm-prepare --v"
|
||||
Then stderr should be empty
|
||||
And stdout should contain 1 line
|
||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: osrm-prepare - Version, long
|
||||
When I run "osrm-prepare --version"
|
||||
Then stderr should be empty
|
||||
And stdout should contain 1 line
|
||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||
And it should exit with code 0
|
||||
@@ -1,5 +1,5 @@
|
||||
@routing @options @files
|
||||
Feature: Command line options: files
|
||||
@routed @options @files
|
||||
Feature: osrm-routed command line options: files
|
||||
# Normally when launching osrm-routed, it will keep running as a server until it's shut down.
|
||||
# For testing program options, the --trial option is used, which causes osrm-routed to quit
|
||||
# immediately after initialization. This makes testing easier and faster.
|
||||
@@ -14,9 +14,9 @@ Feature: Command line options: files
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
And I preprocess data
|
||||
And the data has been prepared
|
||||
|
||||
Scenario: Passing base file
|
||||
Scenario: osrm-routed - Passing base file
|
||||
When I run "osrm-routed {base}.osrm --trial"
|
||||
Then stdout should contain /^\[info\] starting up engines/
|
||||
And stdout should contain /\d{1,2}\.\d{1,2}\.\d{1,2}/
|
||||
@@ -24,4 +24,4 @@ Feature: Command line options: files
|
||||
And stdout should contain /^\[info\] loaded plugin: viaroute/
|
||||
And stdout should contain /^\[info\] trial run/
|
||||
And stdout should contain /^\[info\] shutdown completed/
|
||||
And it should exit with code 0
|
||||
And it should exit with code 0
|
||||
@@ -1,10 +1,10 @@
|
||||
@routing @options
|
||||
Feature: Command line options: help
|
||||
@routed @options @help
|
||||
Feature: osrm-routed command line options: help
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Help should be shown when no options are passed
|
||||
Scenario: osrm-routed - Help should be shown when no options are passed
|
||||
When I run "osrm-routed"
|
||||
Then stderr should be empty
|
||||
And stdout should contain "osrm-routed <base.osrm> [<options>]:"
|
||||
@@ -25,9 +25,10 @@ Feature: Command line options: help
|
||||
And stdout should contain "--port"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain "--sharedmemory"
|
||||
And stdout should contain 22 lines
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: Help, short
|
||||
Scenario: osrm-routed - Help, short
|
||||
When I run "osrm-routed -h"
|
||||
Then stderr should be empty
|
||||
And stdout should contain "osrm-routed <base.osrm> [<options>]:"
|
||||
@@ -48,9 +49,10 @@ Feature: Command line options: help
|
||||
And stdout should contain "--port"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain "--sharedmemory"
|
||||
And stdout should contain 22 lines
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: Help, long
|
||||
Scenario: osrm-routed - Help, long
|
||||
When I run "osrm-routed --help"
|
||||
Then stderr should be empty
|
||||
And stdout should contain "osrm-routed <base.osrm> [<options>]:"
|
||||
@@ -71,4 +73,5 @@ Feature: Command line options: help
|
||||
And stdout should contain "--port"
|
||||
And stdout should contain "--threads"
|
||||
And stdout should contain "--sharedmemory"
|
||||
And it should exit with code 0
|
||||
And stdout should contain 22 lines
|
||||
And it should exit with code 0
|
||||
@@ -1,17 +1,17 @@
|
||||
@routing @options
|
||||
Feature: Command line options: invalid options
|
||||
@routed @options @invalid
|
||||
Feature: osrm-routed command line options: invalid options
|
||||
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Non-existing option
|
||||
Scenario: osrm-routed - Non-existing option
|
||||
When I run "osrm-routed --fly-me-to-the-moon"
|
||||
Then stdout should be empty
|
||||
And stderr should contain "exception"
|
||||
And stderr should contain "fly-me-to-the-moon"
|
||||
And it should exit with code 1
|
||||
|
||||
Scenario: Missing file
|
||||
Scenario: osrm-routed - Missing file
|
||||
When I run "osrm-routed over-the-rainbow.osrm"
|
||||
Then stdout should contain "over-the-rainbow.osrm"
|
||||
And stderr should contain "exception"
|
||||
@@ -1,5 +1,5 @@
|
||||
@routing @options
|
||||
Feature: Command line options: version
|
||||
@routed @options @version
|
||||
Feature: osrm-routed command line options: version
|
||||
# the regex will match these two formats:
|
||||
# v0.3.7.0 # this is the normal format when you build from a git clone
|
||||
# -128-NOTFOUND # if you build from a shallow clone (used on Travis)
|
||||
@@ -7,14 +7,14 @@ Feature: Command line options: version
|
||||
Background:
|
||||
Given the profile "testbot"
|
||||
|
||||
Scenario: Version, short
|
||||
Scenario: osrm-routed - Version, short
|
||||
When I run "osrm-routed --v"
|
||||
Then stderr should be empty
|
||||
And stdout should contain 1 line
|
||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||
And it should exit with code 0
|
||||
|
||||
Scenario: Version, long
|
||||
Scenario: osrm-routed - Version, long
|
||||
When I run "osrm-routed --version"
|
||||
Then stderr should be empty
|
||||
And stdout should contain 1 line
|
||||
@@ -133,3 +133,28 @@ Given /^the input file ([^"]*)$/ do |file|
|
||||
raise "*** Input file must in .osm format" unless File.extname(file)=='.osm'
|
||||
@osm_str = File.read file
|
||||
end
|
||||
|
||||
Given /^the data has been saved to disk$/ do
|
||||
begin
|
||||
write_input_data
|
||||
rescue OSRMError => e
|
||||
@process_error = e
|
||||
end
|
||||
end
|
||||
|
||||
Given /^the data has been extracted$/ do
|
||||
begin
|
||||
write_input_data
|
||||
extract_data unless extracted?
|
||||
rescue OSRMError => e
|
||||
@process_error = e
|
||||
end
|
||||
end
|
||||
|
||||
Given /^the data has been prepared$/ do
|
||||
begin
|
||||
reprocess
|
||||
rescue OSRMError => e
|
||||
@process_error = e
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
When(/^I run "osrm\-routed\s?(.*?)"$/) do |options|
|
||||
Dir.chdir TEST_FOLDER do
|
||||
if options.include? '{base}'
|
||||
# expand {base} to base path of preprocessed data file
|
||||
raise "*** Cannot expand {base} without a preprocessed file." unless @osm_file
|
||||
options_expanded = options.gsub "{base}", "#{@osm_file}"
|
||||
else
|
||||
options_expanded = options
|
||||
end
|
||||
|
||||
begin
|
||||
Timeout.timeout(1) do
|
||||
@stdout = `#{BIN_PATH}/osrm-routed #{options_expanded} 2>error.log`
|
||||
@stderr = File.read 'error.log'
|
||||
@exit_code = $?.exitstatus
|
||||
end
|
||||
rescue Timeout::Error
|
||||
raise "*** osrm-routed didn't quit. Maybe the --trial option wasn't used?"
|
||||
end
|
||||
begin
|
||||
Timeout.timeout(1) { run_bin 'osrm-routed', options }
|
||||
rescue Timeout::Error
|
||||
raise "*** osrm-routed didn't quit. Maybe the --trial option wasn't used?"
|
||||
end
|
||||
end
|
||||
|
||||
When(/^I run "osrm\-extract\s?(.*?)"$/) do |options|
|
||||
run_bin 'osrm-extract', options
|
||||
end
|
||||
|
||||
When(/^I run "osrm\-prepare\s?(.*?)"$/) do |options|
|
||||
run_bin 'osrm-prepare', options
|
||||
end
|
||||
|
||||
Then /^it should exit with code (\d+)$/ do |code|
|
||||
@exit_code.should == code.to_i
|
||||
end
|
||||
|
||||
@@ -29,16 +29,8 @@ Then /^response should be a well-formed route$/ do
|
||||
@json['via_indices'].class.should == Array
|
||||
end
|
||||
|
||||
When /^I preprocess data$/ do
|
||||
begin
|
||||
reprocess
|
||||
rescue OSRMError => e
|
||||
@process_error = e
|
||||
end
|
||||
end
|
||||
|
||||
Then /^"([^"]*)" should return code (\d+)$/ do |binary, code|
|
||||
@process_error.is_a?(OSRMError).should == true
|
||||
@process_error.process.should == binary
|
||||
@process_error.code.to_i.should == code.to_i
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user