Compare commits
172 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b0b378abc | |||
| 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, NodeID> RestrictionSource;
|
||||||
typedef std::pair<NodeID, bool> restriction_target;
|
typedef std::pair<NodeID, bool> restriction_target;
|
||||||
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
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<NodeInfo> m_coordinate_list;
|
||||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
@@ -145,7 +145,7 @@ public:
|
|||||||
if(restriction_iterator == m_restriction_map.end()) {
|
if(restriction_iterator == m_restriction_map.end()) {
|
||||||
index = m_restriction_bucket_list.size();
|
index = m_restriction_bucket_list.size();
|
||||||
m_restriction_bucket_list.resize(index+1);
|
m_restriction_bucket_list.resize(index+1);
|
||||||
m_restriction_map[restrictionSource] = index;
|
m_restriction_map.insert(std::make_pair(restrictionSource, index));
|
||||||
} else {
|
} else {
|
||||||
index = restriction_iterator->second;
|
index = restriction_iterator->second;
|
||||||
//Map already contains an is_only_*-restriction
|
//Map already contains an is_only_*-restriction
|
||||||
@@ -358,6 +358,7 @@ public:
|
|||||||
"identified: " << component_size_vector.size() <<
|
"identified: " << component_size_vector.size() <<
|
||||||
" many components, marking small components";
|
" many components, marking small components";
|
||||||
|
|
||||||
|
// TODO/C++11: prime candidate for lambda function
|
||||||
unsigned size_one_counter = 0;
|
unsigned size_one_counter = 0;
|
||||||
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
|
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
|
||||||
if(1 == component_size_vector[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")
|
message(STATUS "Configuring OSRM in debug mode")
|
||||||
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
message(STATUS "adding profiling flags")
|
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")
|
set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@@ -92,7 +92,7 @@ endif()
|
|||||||
# Configuring compilers
|
# Configuring compilers
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
# using 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++")
|
message(STATUS "OpenMP parallelization not available using clang++")
|
||||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
# using GCC
|
# using GCC
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ public:
|
|||||||
newEdge.source = diter->source();
|
newEdge.source = diter->source();
|
||||||
newEdge.target = diter->target();
|
newEdge.target = diter->target();
|
||||||
newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
|
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" );
|
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
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) ) {
|
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// TODO: C++11 copy_if with lambda
|
||||||
neighbours.push_back( target );
|
neighbours.push_back( target );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,13 +33,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
//TODO: CompressionWorker
|
#include <fstream>
|
||||||
//TODO: EdgeBasedEdgeGenerator
|
#include <iomanip>
|
||||||
|
#include <numeric>
|
||||||
// template<class Work>
|
|
||||||
// inline static void TraverseGraph(NodeBasedDynamicGraph & graph, Work & work) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||||
int number_of_nodes,
|
int number_of_nodes,
|
||||||
@@ -48,12 +44,14 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|||||||
std::vector<NodeID> & traffic_light_node_list,
|
std::vector<NodeID> & traffic_light_node_list,
|
||||||
std::vector<TurnRestriction> & input_restrictions_list,
|
std::vector<TurnRestriction> & input_restrictions_list,
|
||||||
std::vector<NodeInfo> & m_node_info_list,
|
std::vector<NodeInfo> & m_node_info_list,
|
||||||
SpeedProfileProperties speed_profile
|
SpeedProfileProperties & speed_profile
|
||||||
) : speed_profile(speed_profile),
|
) : speed_profile(speed_profile),
|
||||||
m_turn_restrictions_count(0),
|
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::pair<NodeID, NodeID> restriction_source =
|
||||||
std::make_pair(restriction.fromNode, restriction.viaNode);
|
std::make_pair(restriction.fromNode, restriction.viaNode);
|
||||||
unsigned index;
|
unsigned index;
|
||||||
@@ -80,7 +78,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_barrier_nodes.insert(
|
m_barrier_nodes.insert(
|
||||||
barrier_node_list.begin(),
|
barrier_node_list.begin(),
|
||||||
barrier_node_list.end()
|
barrier_node_list.end()
|
||||||
);
|
);
|
||||||
@@ -90,10 +88,15 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|||||||
traffic_light_node_list.end()
|
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;
|
NodeBasedEdge edge;
|
||||||
BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) {
|
BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) {
|
||||||
if(!import_edge.isForward()) {
|
|
||||||
|
if( !import_edge.isForward() ) {
|
||||||
edge.source = import_edge.target();
|
edge.source = import_edge.target();
|
||||||
edge.target = import_edge.source();
|
edge.target = import_edge.source();
|
||||||
edge.data.backward = import_edge.isForward();
|
edge.data.backward = import_edge.isForward();
|
||||||
@@ -104,33 +107,101 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|||||||
edge.data.forward = import_edge.isForward();
|
edge.data.forward = import_edge.isForward();
|
||||||
edge.data.backward = import_edge.isBackward();
|
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 );
|
edge.data.distance = (std::max)((int)import_edge.weight(), 1 );
|
||||||
BOOST_ASSERT( edge.data.distance > 0 );
|
BOOST_ASSERT( edge.data.distance > 0 );
|
||||||
edge.data.shortcut = false;
|
edge.data.shortcut = false;
|
||||||
edge.data.roundabout = import_edge.isRoundabout();
|
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.nameID = import_edge.name();
|
||||||
edge.data.type = import_edge.type();
|
edge.data.type = import_edge.type();
|
||||||
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
|
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
|
||||||
edge.data.edgeBasedNodeID = edges_list.size();
|
|
||||||
edge.data.contraFlow = import_edge.isContraFlow();
|
edge.data.contraFlow = import_edge.isContraFlow();
|
||||||
edges_list.push_back( edge );
|
edges_list.push_back( edge );
|
||||||
if( edge.data.backward ) {
|
|
||||||
std::swap( edge.source, edge.target );
|
if( !import_edge.IsSplit() ) {
|
||||||
edge.data.forward = import_edge.isBackward();
|
using std::swap; //enable ADL
|
||||||
edge.data.backward = import_edge.isForward();
|
swap( edge.source, edge.target );
|
||||||
edge.data.edgeBasedNodeID = edges_list.size();
|
edge.data.SwapDirectionFlags();
|
||||||
edges_list.push_back( edge );
|
edges_list.push_back( edge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ImportEdge>().swap(input_edge_list);
|
std::vector<ImportEdge>().swap(input_edge_list);
|
||||||
std::sort( edges_list.begin(), edges_list.end() );
|
std::sort( edges_list.begin(), edges_list.end() );
|
||||||
|
|
||||||
m_node_based_graph = boost::make_shared<NodeBasedDynamicGraph>(
|
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(
|
void EdgeBasedGraphFactory::GetEdgeBasedEdges(
|
||||||
@@ -146,8 +217,11 @@ void EdgeBasedGraphFactory::GetEdgeBasedEdges(
|
|||||||
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
|
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){
|
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
|
#endif
|
||||||
nodes.swap(m_edge_based_node_list);
|
nodes.swap(m_edge_based_node_list);
|
||||||
@@ -157,7 +231,9 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
|
|||||||
const NodeID u,
|
const NodeID u,
|
||||||
const NodeID v
|
const NodeID v
|
||||||
) const {
|
) 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;
|
RestrictionMap::const_iterator restriction_iter;
|
||||||
restriction_iter = m_restriction_map.find(restriction_source);
|
restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
if (restriction_iter != m_restriction_map.end()) {
|
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(
|
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
||||||
@@ -179,8 +255,11 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
|||||||
const NodeID v,
|
const NodeID v,
|
||||||
const NodeID w
|
const NodeID w
|
||||||
) const {
|
) const {
|
||||||
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
|
||||||
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
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;
|
RestrictionMap::const_iterator restriction_iter;
|
||||||
restriction_iter = m_restriction_map.find(restriction_source);
|
restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
if (restriction_iter != m_restriction_map.end()) {
|
if (restriction_iter != m_restriction_map.end()) {
|
||||||
@@ -189,7 +268,10 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
|||||||
const RestrictionTarget & restriction_target,
|
const RestrictionTarget & restriction_target,
|
||||||
m_restriction_bucket_list.at(index)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,22 +280,175 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
|
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
|
||||||
EdgeIterator e1,
|
NodeIterator u,
|
||||||
NodeIterator u,
|
NodeIterator v,
|
||||||
NodeIterator v,
|
EdgeIterator e1,
|
||||||
bool belongsToTinyComponent) {
|
bool belongs_to_tiny_cc
|
||||||
EdgeData & data = m_node_based_graph->GetEdgeData(e1);
|
) {
|
||||||
EdgeBasedNode currentNode;
|
// merge edges together into one EdgeBasedNode
|
||||||
currentNode.nameID = data.nameID;
|
BOOST_ASSERT( u != SPECIAL_NODEID );
|
||||||
currentNode.lat1 = m_node_info_list[u].lat;
|
BOOST_ASSERT( v != SPECIAL_NODEID );
|
||||||
currentNode.lon1 = m_node_info_list[u].lon;
|
BOOST_ASSERT( e1 != SPECIAL_EDGEID );
|
||||||
currentNode.lat2 = m_node_info_list[v].lat;
|
|
||||||
currentNode.lon2 = m_node_info_list[v].lon;
|
#ifndef NDEBUG
|
||||||
currentNode.belongsToTinyComponent = belongsToTinyComponent;
|
// find forward edge id and
|
||||||
currentNode.id = data.edgeBasedNodeID;
|
const EdgeID e1b = m_node_based_graph->FindEdge(u, v);
|
||||||
currentNode.ignoreInGrid = data.ignoreInGrid;
|
BOOST_ASSERT( e1 == e1b );
|
||||||
currentNode.weight = data.distance;
|
#endif
|
||||||
m_edge_based_node_list.push_back(currentNode);
|
|
||||||
|
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(
|
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
|
lua_State *lua_state
|
||||||
) {
|
) {
|
||||||
SimpleLogger().Write() << "Compressing geometry of input graph";
|
SimpleLogger().Write() << "Removing graph geometry while preserving topology";
|
||||||
//TODO: iterate over all turns
|
|
||||||
|
|
||||||
//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";
|
SimpleLogger().Write() << "Identifying components of the road network";
|
||||||
|
|
||||||
unsigned skipped_turns_counter = 0;
|
|
||||||
unsigned node_based_edge_counter = 0;
|
unsigned node_based_edge_counter = 0;
|
||||||
unsigned original_edges_counter = 0;
|
unsigned original_edges_counter = 0;
|
||||||
|
|
||||||
std::ofstream edge_data_file(
|
std::ofstream edge_data_file(
|
||||||
original_edge_data_filename,
|
original_edge_data_filename.c_str(),
|
||||||
std::ios::binary
|
std::ios::binary
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -261,49 +642,62 @@ void EdgeBasedGraphFactory::Run(
|
|||||||
|
|
||||||
//Run a BFS on the undirected graph and identify small components
|
//Run a BFS on the undirected graph and identify small components
|
||||||
std::vector<unsigned> component_index_list;
|
std::vector<unsigned> component_index_list;
|
||||||
std::vector<NodeID> component_index_size;
|
std::vector<NodeID > component_index_size;
|
||||||
BFSCompentExplorer( component_index_list, component_index_size);
|
BFSCompentExplorer( component_index_list, component_index_size );
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() <<
|
||||||
"identified: " << component_index_size.size() << " many components";
|
"identified: " << component_index_size.size() << " many components";
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "generating edge-expanded nodes";
|
||||||
"generating edge-expanded nodes";
|
|
||||||
|
|
||||||
Percent p(m_node_based_graph->GetNumberOfNodes());
|
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||||
//loop over all edges and generate new set of nodes.
|
|
||||||
|
//loop over all edges and generate new set of nodes
|
||||||
for(
|
for(
|
||||||
NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
|
NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
|
||||||
u < end;
|
u < end;
|
||||||
++u
|
++u
|
||||||
) {
|
) {
|
||||||
|
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
|
||||||
|
BOOST_ASSERT( u < m_node_based_graph->GetNumberOfNodes() );
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
for(
|
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);
|
last_edge = m_node_based_graph->EndEdges(u);
|
||||||
e1 < last_edge;
|
e1 < last_edge;
|
||||||
++e1
|
++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
|
//Note: edges that end on barrier nodes or on a turn restriction
|
||||||
//may actually be in two distinct components. We choose the smallest
|
//may actually be in two distinct components. We choose the smallest
|
||||||
const unsigned size_of_component = std::min(
|
const unsigned size_of_component = std::min(
|
||||||
component_index_size[component_index_list[u]],
|
component_index_size[component_index_list[u]],
|
||||||
component_index_size[component_index_list[v]]
|
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()
|
m_number_of_edge_based_nodes = numbered_edges_count;
|
||||||
<< "Generated " << m_edge_based_node_list.size() << " nodes in " <<
|
|
||||||
"edge-expanded graph";
|
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() <<
|
||||||
|
" nodes in edge-expanded graph";
|
||||||
SimpleLogger().Write() << "generating edge-expanded edges";
|
SimpleLogger().Write() << "generating edge-expanded edges";
|
||||||
|
|
||||||
std::vector<NodeID>().swap(component_index_size);
|
std::vector<NodeID>().swap(component_index_size);
|
||||||
@@ -322,18 +716,19 @@ void EdgeBasedGraphFactory::Run(
|
|||||||
//Loop over all turns and generate new set of edges.
|
//Loop over all turns and generate new set of edges.
|
||||||
//Three nested loop look super-linear, but we are dealing with a (kind of)
|
//Three nested loop look super-linear, but we are dealing with a (kind of)
|
||||||
//linear number of turns only.
|
//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());
|
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||||
for(
|
for (NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
|
||||||
NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
|
{
|
||||||
u < end;
|
for (EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge_u = m_node_based_graph->EndEdges(u); e1 < last_edge_u; ++e1)
|
||||||
++u
|
{
|
||||||
) {
|
if( !m_node_based_graph->GetEdgeData(e1).forward ) {
|
||||||
for(
|
continue;
|
||||||
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
|
}
|
||||||
last_edge_u = m_node_based_graph->EndEdges(u);
|
|
||||||
e1 < last_edge_u;
|
|
||||||
++e1
|
|
||||||
) {
|
|
||||||
++node_based_edge_counter;
|
++node_based_edge_counter;
|
||||||
const NodeIterator v = m_node_based_graph->GetTarget(e1);
|
const NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||||
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
@@ -345,83 +740,92 @@ void EdgeBasedGraphFactory::Run(
|
|||||||
e2 < last_edge_v;
|
e2 < last_edge_v;
|
||||||
++e2
|
++e2
|
||||||
) {
|
) {
|
||||||
|
if (!m_node_based_graph->GetEdgeData(e2).forward)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const NodeIterator w = m_node_based_graph->GetTarget(e2);
|
const NodeIterator w = m_node_based_graph->GetTarget(e2);
|
||||||
if(
|
|
||||||
to_node_of_only_restriction != UINT_MAX &&
|
if ((to_node_of_only_restriction != SPECIAL_NODEID) && (w != to_node_of_only_restriction))
|
||||||
w != to_node_of_only_restriction
|
{
|
||||||
) {
|
|
||||||
//We are at an only_-restriction but not at the right turn.
|
//We are at an only_-restriction but not at the right turn.
|
||||||
++skipped_turns_counter;
|
++restricted_turns_counter;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( is_barrier_node) {
|
if (is_barrier_node)
|
||||||
if(u != w) {
|
{
|
||||||
++skipped_turns_counter;
|
if (u != w)
|
||||||
|
{
|
||||||
|
++skipped_barrier_turns_counter;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if ( (u == w) && (m_node_based_graph->GetOutDegree(v) > 1) ) {
|
else
|
||||||
++skipped_turns_counter;
|
{
|
||||||
|
if ((u == w) && (m_node_based_graph->GetOutDegree(v) > 1))
|
||||||
|
{
|
||||||
|
++skipped_uturns_counter;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//only add an edge if turn is not a U-turn except when it is
|
//only add an edge if turn is not a U-turn except when it is
|
||||||
//at the end of a dead-end street
|
//at the end of a dead-end street
|
||||||
if (
|
if (CheckIfTurnIsRestricted(u, v, w) && (to_node_of_only_restriction == SPECIAL_NODEID) && (w != to_node_of_only_restriction))
|
||||||
CheckIfTurnIsRestricted(u, v, w) &&
|
{
|
||||||
(to_node_of_only_restriction == UINT_MAX) &&
|
++restricted_turns_counter;
|
||||||
(w != to_node_of_only_restriction)
|
|
||||||
) {
|
|
||||||
++skipped_turns_counter;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//only add an edge if turn is not prohibited
|
//only add an edge if turn is not prohibited
|
||||||
const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1);
|
const EdgeData & edge_data1 = m_node_based_graph->GetEdgeData(e1);
|
||||||
const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2);
|
const EdgeData & edge_data2 = m_node_based_graph->GetEdgeData(e2);
|
||||||
|
|
||||||
BOOST_ASSERT(
|
BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
|
||||||
edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges()
|
BOOST_ASSERT(edge_data1.forward);
|
||||||
);
|
BOOST_ASSERT(edge_data2.forward);
|
||||||
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 );
|
|
||||||
|
|
||||||
// the following is the core of the loop.
|
// the following is the core of the loop.
|
||||||
unsigned distance = edge_data1.distance;
|
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;
|
distance += speed_profile.trafficSignalPenalty;
|
||||||
}
|
}
|
||||||
const int turn_penalty = GetTurnPenalty(u, v, w, lua_state);
|
const int turn_penalty = GetTurnPenalty(u, v, w, lua_state);
|
||||||
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
|
TurnInstruction turn_instruction = AnalyzeTurn(u, v, w);
|
||||||
if(turnInstruction == TurnInstructions.UTurn){
|
if (turn_instruction == TurnInstructionsClass::UTurn)
|
||||||
|
{
|
||||||
distance += speed_profile.uTurnPenalty;
|
distance += speed_profile.uTurnPenalty;
|
||||||
}
|
}
|
||||||
distance += turn_penalty;
|
distance += turn_penalty;
|
||||||
|
|
||||||
|
const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1);
|
||||||
|
|
||||||
|
if (edge_is_compressed)
|
||||||
|
{
|
||||||
|
++compressed;
|
||||||
|
}
|
||||||
|
|
||||||
original_edge_data_vector.push_back(
|
original_edge_data_vector.push_back(
|
||||||
OriginalEdgeData(
|
OriginalEdgeData(
|
||||||
v,
|
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v),
|
||||||
edge_data2.nameID,
|
edge_data1.nameID,
|
||||||
turnInstruction
|
turn_instruction,
|
||||||
|
edge_is_compressed
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
++original_edges_counter;
|
++original_edges_counter;
|
||||||
|
|
||||||
if(original_edge_data_vector.size() > 100000) {
|
if (original_edge_data_vector.size() > 100000)
|
||||||
FlushVectorToStream(
|
{
|
||||||
edge_data_file,
|
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||||
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(
|
m_edge_based_edge_list.push_back(
|
||||||
EdgeBasedEdge(
|
EdgeBasedEdge(
|
||||||
edge_data1.edgeBasedNodeID,
|
edge_data1.edgeBasedNodeID,
|
||||||
@@ -442,17 +846,16 @@ void EdgeBasedGraphFactory::Run(
|
|||||||
edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) );
|
edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) );
|
||||||
edge_data_file.close();
|
edge_data_file.close();
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
m_geometry_compressor.SerializeInternalVector( geometry_filename );
|
||||||
"Generated " << m_edge_based_node_list.size() << " edge based nodes";
|
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes";
|
||||||
"Node-based graph contains " << node_based_edge_counter << " edges";
|
SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges";
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "Edge-expanded graph ...";
|
||||||
"Edge-expanded graph ...";
|
SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges";
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, "
|
||||||
" contains " << m_edge_based_edge_list.size() << " edges";
|
"defined by " << m_turn_restrictions_count << " restrictions";
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns";
|
||||||
" skips " << skipped_turns_counter << " turns, "
|
SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
|
||||||
"defined by " << m_turn_restrictions_count << " restrictions";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int EdgeBasedGraphFactory::GetTurnPenalty(
|
int EdgeBasedGraphFactory::GetTurnPenalty(
|
||||||
@@ -488,7 +891,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
|||||||
const NodeID w
|
const NodeID w
|
||||||
) const {
|
) const {
|
||||||
if(u == w) {
|
if(u == w) {
|
||||||
return TurnInstructions.UTurn;
|
return TurnInstructionsClass::UTurn;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
|
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);
|
const EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
|
||||||
|
|
||||||
if(!data1.contraFlow && data2.contraFlow) {
|
if(!data1.contraFlow && data2.contraFlow) {
|
||||||
return TurnInstructions.EnterAgainstAllowedDirection;
|
return TurnInstructionsClass::EnterAgainstAllowedDirection;
|
||||||
}
|
}
|
||||||
if(data1.contraFlow && !data2.contraFlow) {
|
if(data1.contraFlow && !data2.contraFlow) {
|
||||||
return TurnInstructions.LeaveAgainstAllowedDirection;
|
return TurnInstructionsClass::LeaveAgainstAllowedDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
//roundabouts need to be handled explicitely
|
//roundabouts need to be handled explicitely
|
||||||
@@ -509,19 +912,19 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
|||||||
//Is a turn possible? If yes, we stay on the roundabout!
|
//Is a turn possible? If yes, we stay on the roundabout!
|
||||||
if( 1 == m_node_based_graph->GetOutDegree(v) ) {
|
if( 1 == m_node_based_graph->GetOutDegree(v) ) {
|
||||||
//No turn possible.
|
//No turn possible.
|
||||||
return TurnInstructions.NoTurn;
|
return TurnInstructionsClass::NoTurn;
|
||||||
}
|
}
|
||||||
return TurnInstructions.StayOnRoundAbout;
|
return TurnInstructionsClass::StayOnRoundAbout;
|
||||||
}
|
}
|
||||||
//Does turn start or end on roundabout?
|
//Does turn start or end on roundabout?
|
||||||
if(data1.roundabout || data2.roundabout) {
|
if(data1.roundabout || data2.roundabout) {
|
||||||
//We are entering the roundabout
|
//We are entering the roundabout
|
||||||
if( (!data1.roundabout) && data2.roundabout) {
|
if( (!data1.roundabout) && data2.roundabout) {
|
||||||
return TurnInstructions.EnterRoundAbout;
|
return TurnInstructionsClass::EnterRoundAbout;
|
||||||
}
|
}
|
||||||
//We are leaving the roundabout
|
//We are leaving the roundabout
|
||||||
if(data1.roundabout && (!data2.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
|
//TODO: Here we should also do a small graph exploration to check for
|
||||||
// more complex situations
|
// more complex situations
|
||||||
if( 0 != data1.nameID ) {
|
if( 0 != data1.nameID ) {
|
||||||
return TurnInstructions.NoTurn;
|
return TurnInstructionsClass::NoTurn;
|
||||||
} else if (m_node_based_graph->GetOutDegree(v) <= 2) {
|
} 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[v],
|
||||||
m_node_info_list[w]
|
m_node_info_list[w]
|
||||||
);
|
);
|
||||||
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
|
return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
|
unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const {
|
||||||
return m_node_based_graph->GetNumberOfEdges();
|
return m_number_of_edge_based_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::BFSCompentExplorer(
|
void EdgeBasedGraphFactory::BFSCompentExplorer(
|
||||||
@@ -563,12 +966,12 @@ void EdgeBasedGraphFactory::BFSCompentExplorer(
|
|||||||
|
|
||||||
component_index_list.resize(
|
component_index_list.resize(
|
||||||
m_node_based_graph->GetNumberOfNodes(),
|
m_node_based_graph->GetNumberOfNodes(),
|
||||||
UINT_MAX
|
std::numeric_limits<unsigned>::max()
|
||||||
);
|
);
|
||||||
|
|
||||||
//put unexplorered node with parent pointer into queue
|
//put unexplorered node with parent pointer into queue
|
||||||
for( NodeID node = 0, end = m_node_based_graph->GetNumberOfNodes(); node < end; ++node) {
|
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));
|
bfs_queue.push(std::make_pair(node, node));
|
||||||
//mark node as read
|
//mark node as read
|
||||||
component_index_list[node] = current_component;
|
component_index_list[node] = current_component;
|
||||||
@@ -594,7 +997,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer(
|
|||||||
NodeIterator w = m_node_based_graph->GetTarget(e2);
|
NodeIterator w = m_node_based_graph->GetTarget(e2);
|
||||||
|
|
||||||
if(
|
if(
|
||||||
to_node_of_only_restriction != UINT_MAX &&
|
to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||||
w != to_node_of_only_restriction
|
w != to_node_of_only_restriction
|
||||||
) {
|
) {
|
||||||
// At an only_-restriction but not at the right turn
|
// 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.
|
//when it is at the end of a dead-end street.
|
||||||
if (!CheckIfTurnIsRestricted(u, v, w) ) {
|
if (!CheckIfTurnIsRestricted(u, v, w) ) {
|
||||||
//only add an edge if turn is not prohibited
|
//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
|
//insert next (node, parent) only if w has
|
||||||
//not yet been explored
|
//not yet been explored
|
||||||
//mark node as read
|
//mark node as read
|
||||||
|
|||||||
@@ -53,23 +53,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/unordered_set.hpp>
|
#include <boost/unordered_set.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <iosfwd>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class EdgeBasedGraphFactory : boost::noncopyable {
|
class EdgeBasedGraphFactory : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
struct SpeedProfileProperties{
|
struct SpeedProfileProperties;
|
||||||
SpeedProfileProperties() :
|
|
||||||
trafficSignalPenalty(0),
|
|
||||||
uTurnPenalty(0),
|
|
||||||
has_turn_penalty_function(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
int trafficSignalPenalty;
|
|
||||||
int uTurnPenalty;
|
|
||||||
bool has_turn_penalty_function;
|
|
||||||
} speed_profile;
|
|
||||||
|
|
||||||
explicit EdgeBasedGraphFactory(
|
explicit EdgeBasedGraphFactory(
|
||||||
int number_of_nodes,
|
int number_of_nodes,
|
||||||
@@ -78,10 +68,14 @@ public:
|
|||||||
std::vector<NodeID> & traffic_light_node_list,
|
std::vector<NodeID> & traffic_light_node_list,
|
||||||
std::vector<TurnRestriction> & input_restrictions_list,
|
std::vector<TurnRestriction> & input_restrictions_list,
|
||||||
std::vector<NodeInfo> & m_node_info_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 );
|
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
||||||
|
|
||||||
@@ -100,10 +94,27 @@ public:
|
|||||||
lua_State *myLuaState
|
lua_State *myLuaState
|
||||||
) const;
|
) 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:
|
private:
|
||||||
struct NodeBasedEdgeData {
|
struct NodeBasedEdgeData {
|
||||||
|
NodeBasedEdgeData() {
|
||||||
|
//TODO: proper c'tor
|
||||||
|
edgeBasedNodeID = UINT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
int distance;
|
int distance;
|
||||||
unsigned edgeBasedNodeID;
|
unsigned edgeBasedNodeID;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
@@ -113,11 +124,26 @@ private:
|
|||||||
bool forward:1;
|
bool forward:1;
|
||||||
bool backward:1;
|
bool backward:1;
|
||||||
bool roundabout:1;
|
bool roundabout:1;
|
||||||
bool ignoreInGrid:1;
|
bool ignore_in_grid:1;
|
||||||
bool contraFlow: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_turn_restrictions_count;
|
||||||
|
unsigned m_number_of_edge_based_nodes;
|
||||||
|
|
||||||
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||||
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
|
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
|
||||||
@@ -139,6 +165,7 @@ private:
|
|||||||
boost::unordered_set<NodeID> m_traffic_lights;
|
boost::unordered_set<NodeID> m_traffic_lights;
|
||||||
|
|
||||||
RestrictionMap m_restriction_map;
|
RestrictionMap m_restriction_map;
|
||||||
|
GeometryCompressor m_geometry_compressor;
|
||||||
|
|
||||||
NodeID CheckForEmanatingIsOnlyTurn(
|
NodeID CheckForEmanatingIsOnlyTurn(
|
||||||
const NodeID u,
|
const NodeID u,
|
||||||
@@ -152,9 +179,9 @@ private:
|
|||||||
) const;
|
) const;
|
||||||
|
|
||||||
void InsertEdgeBasedNode(
|
void InsertEdgeBasedNode(
|
||||||
NodeBasedDynamicGraph::EdgeIterator e1,
|
|
||||||
NodeBasedDynamicGraph::NodeIterator u,
|
NodeBasedDynamicGraph::NodeIterator u,
|
||||||
NodeBasedDynamicGraph::NodeIterator v,
|
NodeBasedDynamicGraph::NodeIterator v,
|
||||||
|
NodeBasedDynamicGraph::EdgeIterator e1,
|
||||||
bool belongsToTinyComponent
|
bool belongsToTinyComponent
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -167,6 +194,20 @@ private:
|
|||||||
std::ofstream & edge_data_file,
|
std::ofstream & edge_data_file,
|
||||||
std::vector<OriginalEdgeData> & original_edge_data_vector
|
std::vector<OriginalEdgeData> & original_edge_data_vector
|
||||||
) const;
|
) 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_ */
|
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
||||||
|
|||||||
@@ -26,69 +26,199 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "GeometryCompressor.h"
|
#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 current_free_list_maximum = 0;
|
||||||
int UniqueNumber () { return ++current_free_list_maximum; }
|
int UniqueNumber() { return ++current_free_list_maximum; }
|
||||||
|
|
||||||
GeometryCompressor::GeometryCompressor() {
|
GeometryCompressor::GeometryCompressor()
|
||||||
m_free_list.resize(100);
|
{
|
||||||
|
m_free_list.reserve(100);
|
||||||
IncreaseFreeList();
|
IncreaseFreeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryCompressor::IncreaseFreeList() {
|
void GeometryCompressor::IncreaseFreeList()
|
||||||
|
{
|
||||||
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
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 ) {
|
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
||||||
//check if node_id already has a list
|
{
|
||||||
boost::unordered_map<unsigned, unsigned>::const_iterator map_iterator;
|
return (m_edge_id_to_list_index_map.find(edge_id) != m_edge_id_to_list_index_map.end());
|
||||||
map_iterator = m_node_id_to_index_map.find( node_id );
|
}
|
||||||
|
|
||||||
unsigned geometry_bucket_index = std::numeric_limits<unsigned>::max();
|
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
|
||||||
if( m_node_id_to_index_map.end() == map_iterator ) {
|
{
|
||||||
//if not, create one
|
boost::unordered_map<EdgeID, unsigned>::const_iterator map_iterator;
|
||||||
if( m_free_list.empty() ) {
|
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();
|
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();
|
m_free_list.pop_back();
|
||||||
} else {
|
|
||||||
geometry_bucket_index = map_iterator->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != geometry_bucket_index );
|
const unsigned edge_bucket_id1 = m_edge_id_to_list_index_map[edge_id_1];
|
||||||
BOOST_ASSERT( geometry_bucket_index < m_compressed_geometries.size() );
|
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]
|
std::vector<CompressedNode> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
|
||||||
m_compressed_geometries[geometry_bucket_index].push_back(contracted_node_id);
|
|
||||||
|
|
||||||
//append m_compressed_geometries[contracted_node_id] to m_compressed_geometries[node_id]
|
if (edge_bucket_list1.empty())
|
||||||
map_iterator = m_node_id_to_index_map.find(contracted_node_id);
|
{
|
||||||
if ( m_node_id_to_index_map.end() != map_iterator) {
|
edge_bucket_list1.push_back(std::make_pair(via_node_id, weight1));
|
||||||
const unsigned bucket_index_to_remove = map_iterator->second;
|
}
|
||||||
BOOST_ASSERT( bucket_index_to_remove < m_compressed_geometries.size() );
|
|
||||||
|
|
||||||
m_compressed_geometries[geometry_bucket_index].insert(
|
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
||||||
m_compressed_geometries[geometry_bucket_index].end(),
|
BOOST_ASSERT(!edge_bucket_list1.empty());
|
||||||
m_compressed_geometries[bucket_index_to_remove].begin(),
|
|
||||||
m_compressed_geometries[bucket_index_to_remove].end()
|
if (HasEntryForID(edge_id_2))
|
||||||
);
|
{
|
||||||
//remove m_compressed_geometries[contracted_node_id], add to free list
|
// second edge is not atomic anymore
|
||||||
m_compressed_geometries[bucket_index_to_remove].clear();
|
const unsigned list_to_remove_index = GetPositionForID(edge_id_2);
|
||||||
m_free_list.push_back(bucket_index_to_remove);
|
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 {
|
void GeometryCompressor::PrintStatistics() const
|
||||||
unsigned compressed_node_count = 0;
|
{
|
||||||
const unsigned surviving_node_count = m_compressed_geometries.size();
|
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) {
|
uint64_t number_of_compressed_geometries = 0;
|
||||||
compressed_node_count += current_vector.size();
|
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 <<
|
SimpleLogger().Write() << "Geometry successfully removed:"
|
||||||
", comp: " << compressed_node_count <<
|
"\n compressed edges: " << compressed_edges
|
||||||
", comp ratio: " << ((float)surviving_node_count/std::max(compressed_node_count, 1u) );
|
<< "\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 "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifndef GEOMETRY_COMPRESSOR_H
|
#ifndef GEOMETRY_COMPRESSOR_H
|
||||||
#define GEOMETRY_COMPRESSOR_H
|
#define GEOMETRY_COMPRESSOR_H
|
||||||
|
|
||||||
class GeometryCompressor {
|
class GeometryCompressor
|
||||||
public:
|
{
|
||||||
|
public:
|
||||||
|
typedef std::pair<NodeID, EdgeWeight> CompressedNode;
|
||||||
|
|
||||||
GeometryCompressor();
|
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 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();
|
void IncreaseFreeList();
|
||||||
|
std::vector<std::vector<CompressedNode> > m_compressed_geometries;
|
||||||
std::vector<std::vector<unsigned> > m_compressed_geometries;
|
|
||||||
std::vector<unsigned> m_free_list;
|
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 {
|
class ArrayStorage {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ArrayStorage( size_t size ) : positions( new Key[size] ) {
|
explicit ArrayStorage( size_t size ) : positions( new Key[size] ) {
|
||||||
memset(positions, 0, size*sizeof(Key));
|
memset(positions, 0, size*sizeof(Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ template< typename NodeID, typename Key >
|
|||||||
class MapStorage {
|
class MapStorage {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MapStorage( size_t ) {}
|
explicit MapStorage( size_t ) {}
|
||||||
|
|
||||||
Key &operator[]( NodeID node ) {
|
Key &operator[]( NodeID node ) {
|
||||||
return nodes[node];
|
return nodes[node];
|
||||||
@@ -87,7 +87,7 @@ class UnorderedMapStorage {
|
|||||||
typedef typename UnorderedMapType::const_iterator UnorderedMapConstIterator;
|
typedef typename UnorderedMapType::const_iterator UnorderedMapConstIterator;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
UnorderedMapStorage( size_t ) {
|
explicit UnorderedMapStorage( size_t ) {
|
||||||
//hash table gets 1000 Buckets
|
//hash table gets 1000 Buckets
|
||||||
nodes.rehash(1000);
|
nodes.rehash(1000);
|
||||||
}
|
}
|
||||||
@@ -96,6 +96,11 @@ public:
|
|||||||
return nodes[node];
|
return nodes[node];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Key const & operator[]( const NodeID node ) const {
|
||||||
|
UnorderedMapConstIterator iter = nodes.find(node);
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
nodes.clear();
|
nodes.clear();
|
||||||
}
|
}
|
||||||
@@ -119,7 +124,7 @@ public:
|
|||||||
typedef Weight WeightType;
|
typedef Weight WeightType;
|
||||||
typedef Data DataType;
|
typedef Data DataType;
|
||||||
|
|
||||||
BinaryHeap( size_t maxID )
|
explicit BinaryHeap( size_t maxID )
|
||||||
:
|
:
|
||||||
nodeIndex( maxID )
|
nodeIndex( maxID )
|
||||||
{
|
{
|
||||||
@@ -158,6 +163,11 @@ public:
|
|||||||
return insertedNodes[index].data;
|
return insertedNodes[index].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Data const & GetData( NodeID node ) const {
|
||||||
|
const Key index = nodeIndex[node];
|
||||||
|
return insertedNodes[index].data;
|
||||||
|
}
|
||||||
|
|
||||||
Weight& GetKey( NodeID node ) {
|
Weight& GetKey( NodeID node ) {
|
||||||
const Key index = nodeIndex[node];
|
const Key index = nodeIndex[node];
|
||||||
return insertedNodes[index].weight;
|
return insertedNodes[index].weight;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ template<typename Data>
|
|||||||
class ConcurrentQueue {
|
class ConcurrentQueue {
|
||||||
|
|
||||||
public:
|
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) {
|
inline void push(const Data & data) {
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
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 <osrm/Coordinate.h>
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <cmath>
|
|
||||||
#include <climits>
|
#ifndef NDEBUG
|
||||||
|
#include <bitset>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
FixedPointCoordinate::FixedPointCoordinate()
|
FixedPointCoordinate::FixedPointCoordinate()
|
||||||
: lat(INT_MIN),
|
: lat(std::numeric_limits<int>::min()),
|
||||||
lon(INT_MIN)
|
lon(std::numeric_limits<int>::min())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon)
|
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon)
|
||||||
: lat(lat),
|
: lat(lat),
|
||||||
lon(lon)
|
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() {
|
void FixedPointCoordinate::Reset() {
|
||||||
lat = INT_MIN;
|
lat = std::numeric_limits<int>::min();
|
||||||
lon = INT_MIN;
|
lon = std::numeric_limits<int>::min();
|
||||||
}
|
}
|
||||||
bool FixedPointCoordinate::isSet() const {
|
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 {
|
bool FixedPointCoordinate::isValid() const {
|
||||||
if(
|
if (lat > 90*COORDINATE_PRECISION ||
|
||||||
lat > 90*COORDINATE_PRECISION ||
|
|
||||||
lat < -90*COORDINATE_PRECISION ||
|
lat < -90*COORDINATE_PRECISION ||
|
||||||
lon > 180*COORDINATE_PRECISION ||
|
lon > 180*COORDINATE_PRECISION ||
|
||||||
lon < -180*COORDINATE_PRECISION
|
lon < -180*COORDINATE_PRECISION)
|
||||||
) {
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -70,10 +88,10 @@ double FixedPointCoordinate::ApproximateDistance(
|
|||||||
const int lat2,
|
const int lat2,
|
||||||
const int lon2
|
const int lon2
|
||||||
) {
|
) {
|
||||||
BOOST_ASSERT(lat1 != INT_MIN);
|
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(lon1 != INT_MIN);
|
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(lat2 != INT_MIN);
|
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(lon2 != INT_MIN);
|
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||||
double RAD = 0.017453292519943295769236907684886;
|
double RAD = 0.017453292519943295769236907684886;
|
||||||
double lt1 = lat1/COORDINATE_PRECISION;
|
double lt1 = lat1/COORDINATE_PRECISION;
|
||||||
double ln1 = lon1/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)
|
//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)
|
//The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||||
const double earth=6372797.560856;
|
const double earth=6372797.560856;
|
||||||
double distance=earth*cHarv;
|
return earth*cHarv;
|
||||||
return distance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double FixedPointCoordinate::ApproximateDistance(
|
double FixedPointCoordinate::ApproximateDistance(
|
||||||
const FixedPointCoordinate &c1,
|
const FixedPointCoordinate &c1,
|
||||||
const FixedPointCoordinate &c2
|
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(
|
double FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||||
const FixedPointCoordinate &c1,
|
const FixedPointCoordinate &c1,
|
||||||
const FixedPointCoordinate &c2
|
const FixedPointCoordinate &c2
|
||||||
) {
|
) {
|
||||||
BOOST_ASSERT(c1.lat != INT_MIN);
|
BOOST_ASSERT(c1.lat != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(c1.lon != INT_MIN);
|
BOOST_ASSERT(c1.lon != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(c2.lat != INT_MIN);
|
BOOST_ASSERT(c2.lat != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(c2.lon != INT_MIN);
|
BOOST_ASSERT(c2.lon != std::numeric_limits<int>::min());
|
||||||
const double RAD = 0.017453292519943295769236907684886;
|
const double RAD = 0.017453292519943295769236907684886;
|
||||||
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
|
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
|
||||||
const double lon1 = (c1.lon/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 x = (lon2-lon1) * cos((lat1+lat2)/2.);
|
||||||
const double y = (lat2-lat1);
|
const double y = (lat2-lat1);
|
||||||
const double earthRadius = 6372797.560856;
|
const double earthRadius = 6372797.560856;
|
||||||
const double d = sqrt(x*x + y*y) * earthRadius;
|
return sqrt(x*x + y*y) * earthRadius;
|
||||||
return d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedPointCoordinate::convertInternalLatLonToString(
|
void FixedPointCoordinate::convertInternalLatLonToString(
|
||||||
@@ -160,3 +176,8 @@ void FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
|||||||
convertInternalLatLonToString(coord.lon, tmp);
|
convertInternalLatLonToString(coord.lon, tmp);
|
||||||
output += tmp;
|
output += tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FixedPointCoordinate::Output(std::ostream & out) const
|
||||||
|
{
|
||||||
|
out << "(" << lat/COORDINATE_PRECISION << "," << lon/COORDINATE_PRECISION << ")";
|
||||||
|
}
|
||||||
|
|||||||
@@ -96,10 +96,10 @@ public:
|
|||||||
DeallocatingVectorIterator() {}
|
DeallocatingVectorIterator() {}
|
||||||
|
|
||||||
template<typename T2>
|
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(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>
|
template<typename T2>
|
||||||
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class DynamicGraph {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Constructs an empty graph with a given number of nodes.
|
//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.reserve( m_numNodes );
|
||||||
m_nodes.resize( m_numNodes );
|
m_nodes.resize( m_numNodes );
|
||||||
|
|
||||||
|
|||||||
+127
-143
@@ -1,176 +1,160 @@
|
|||||||
#ifndef EDGE_BASED_NODE_H
|
#ifndef EDGE_BASED_NODE_H
|
||||||
#define EDGE_BASED_NODE_H
|
#define EDGE_BASED_NODE_H
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include "../Util/MercatorUtil.h"
|
#include "../Util/MercatorUtil.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
// An EdgeBasedNode represents a node in the edge-expanded graph.
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
struct EdgeBasedNode {
|
struct EdgeBasedNode {
|
||||||
|
|
||||||
EdgeBasedNode() :
|
EdgeBasedNode() :
|
||||||
id(INT_MAX),
|
forward_edge_based_node_id(SPECIAL_NODEID),
|
||||||
lat1(INT_MAX),
|
reverse_edge_based_node_id(SPECIAL_NODEID),
|
||||||
lat2(INT_MAX),
|
u(SPECIAL_NODEID),
|
||||||
lon1(INT_MAX),
|
v(SPECIAL_NODEID),
|
||||||
lon2(INT_MAX >> 1),
|
name_id(0),
|
||||||
belongsToTinyComponent(false),
|
forward_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||||
nameID(UINT_MAX),
|
reverse_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||||
weight(UINT_MAX >> 1),
|
forward_offset(0),
|
||||||
ignoreInGrid(false)
|
reverse_offset(0),
|
||||||
|
packed_geometry_id(SPECIAL_EDGEID),
|
||||||
|
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
|
||||||
|
belongsToTinyComponent(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Computes:
|
explicit EdgeBasedNode(
|
||||||
// - the distance from the given query location to nearest point on this edge (and returns it)
|
NodeID forward_edge_based_node_id,
|
||||||
// - the location on this edge which is nearest to the query location
|
NodeID reverse_edge_based_node_id,
|
||||||
// - the ratio ps:pq, where p and q are the end points of this edge, and s is the perpendicular foot of
|
NodeID u,
|
||||||
// the query location on the line defined by p and q.
|
NodeID v,
|
||||||
double ComputePerpendicularDistance(
|
unsigned name_id,
|
||||||
const FixedPointCoordinate& query_location,
|
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,
|
FixedPointCoordinate & nearest_location,
|
||||||
double & ratio,
|
double & r
|
||||||
double precision = COORDINATE_PRECISION
|
) {
|
||||||
) const {
|
|
||||||
BOOST_ASSERT( query_location.isValid() );
|
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 ) {
|
//discretize the result to coordinate precision. it's a hack!
|
||||||
return std::numeric_limits<double>::max();
|
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
|
||||||
|
nY = 0.;
|
||||||
}
|
}
|
||||||
|
|
||||||
// p, q : the end points of the underlying edge
|
r = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
|
||||||
const Point p(lat2y(lat1/COORDINATE_PRECISION), lon1/COORDINATE_PRECISION);
|
// not calculate the explicit values of m an n as we
|
||||||
const Point q(lat2y(lat2/COORDINATE_PRECISION), lon2/COORDINATE_PRECISION);
|
// are just interested in the ratio
|
||||||
|
if( std::isnan(r) ) {
|
||||||
// r : query location
|
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
|
||||||
const Point r(lat2y(query_location.lat/COORDINATE_PRECISION),
|
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
|
||||||
query_location.lon/COORDINATE_PRECISION);
|
r = 0.;
|
||||||
|
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
|
||||||
const Point foot = ComputePerpendicularFoot(p, q, r, epsilon);
|
r = 1.;
|
||||||
ratio = ComputeRatio(p, q, foot, epsilon);
|
}
|
||||||
|
BOOST_ASSERT( !std::isnan(r) );
|
||||||
BOOST_ASSERT( !std::isnan(ratio) );
|
if( r <= 0. ){
|
||||||
|
nearest_location.lat = coord_a.lat;
|
||||||
nearest_location = ComputeNearestPointOnSegment(foot, ratio);
|
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() );
|
BOOST_ASSERT( nearest_location.isValid() );
|
||||||
|
|
||||||
// TODO: Replace with euclidean approximation when k-NN search is done
|
// TODO: Replace with euclidean approximation when k-NN search is done
|
||||||
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||||
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(query_location, nearest_location);
|
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(
|
||||||
|
query_location,
|
||||||
BOOST_ASSERT( 0.0 <= approximated_distance );
|
nearest_location
|
||||||
|
);
|
||||||
|
BOOST_ASSERT( 0. <= approximated_distance );
|
||||||
return approximated_distance;
|
return approximated_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const EdgeBasedNode & other) const {
|
static inline FixedPointCoordinate Centroid(
|
||||||
return other.id < id;
|
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 {
|
bool IsCompressed() {
|
||||||
return id == other.id;
|
return packed_geometry_id != SPECIAL_EDGEID;
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#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
|
#ifndef HASH_TABLE_H
|
||||||
#define HASH_TABLE_H
|
#define HASH_TABLE_H
|
||||||
|
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
template<typename KeyT, typename ValueT>
|
template<typename Key, typename Value, typename Hash = boost::hash<Key> >
|
||||||
class HashTable : public boost::unordered_map<KeyT, ValueT> {
|
class HashTable : public boost::unordered_map<Key, Value> {
|
||||||
private:
|
private:
|
||||||
typedef boost::unordered_map<KeyT, ValueT> super;
|
typedef boost::unordered_map<Key, Value, Hash> super;
|
||||||
public:
|
public:
|
||||||
static ValueT default_value;
|
static Value default_value;
|
||||||
|
|
||||||
HashTable() : super() { }
|
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));
|
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);
|
typename super::const_iterator iter = super::find(key);
|
||||||
if( iter == super::end() ) {
|
if (iter == super::end())
|
||||||
|
{
|
||||||
return boost::cref(default_value);
|
return boost::cref(default_value);
|
||||||
}
|
}
|
||||||
return boost::cref(iter->second);
|
return boost::cref(iter->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Holds( KeyT const & key) const {
|
inline const bool Holds( Key const & key) const
|
||||||
if( super::find(key) == super::end() ) {
|
{
|
||||||
|
if(super::find(key) == super::end())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename KeyT, typename ValueT>
|
template<typename Key, typename Value, typename Hash>
|
||||||
ValueT HashTable<KeyT, ValueT>::default_value;
|
Value HashTable<Key, Value, Hash>::default_value;
|
||||||
|
|
||||||
#endif /* HASH_TABLE_H */
|
#endif /* HASH_TABLE_H */
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ public:
|
|||||||
bool ra,
|
bool ra,
|
||||||
bool ig,
|
bool ig,
|
||||||
bool ar,
|
bool ar,
|
||||||
bool cf
|
bool cf,
|
||||||
|
bool is_split
|
||||||
) : _source(s),
|
) : _source(s),
|
||||||
_target(t),
|
_target(t),
|
||||||
_name(n),
|
_name(n),
|
||||||
@@ -72,7 +73,8 @@ public:
|
|||||||
_roundabout(ra),
|
_roundabout(ra),
|
||||||
_ignoreInGrid(ig),
|
_ignoreInGrid(ig),
|
||||||
_accessRestricted(ar),
|
_accessRestricted(ar),
|
||||||
_contraFlow(cf)
|
_contraFlow(cf),
|
||||||
|
is_split(is_split)
|
||||||
{
|
{
|
||||||
if(ty < 0) {
|
if(ty < 0) {
|
||||||
throw OSRMException("negative edge type");
|
throw OSRMException("negative edge type");
|
||||||
@@ -93,6 +95,7 @@ public:
|
|||||||
bool ignoreInGrid() const { return _ignoreInGrid; }
|
bool ignoreInGrid() const { return _ignoreInGrid; }
|
||||||
bool isAccessRestricted() const { return _accessRestricted; }
|
bool isAccessRestricted() const { return _accessRestricted; }
|
||||||
bool isContraFlow() const { return _contraFlow; }
|
bool isContraFlow() const { return _contraFlow; }
|
||||||
|
bool IsSplit() const { return is_split; }
|
||||||
|
|
||||||
//TODO: names need to be fixed.
|
//TODO: names need to be fixed.
|
||||||
NodeID _source;
|
NodeID _source;
|
||||||
@@ -106,6 +109,7 @@ public:
|
|||||||
bool _ignoreInGrid:1;
|
bool _ignoreInGrid:1;
|
||||||
bool _accessRestricted:1;
|
bool _accessRestricted:1;
|
||||||
bool _contraFlow:1;
|
bool _contraFlow:1;
|
||||||
|
bool is_split:1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeBasedEdge() { }
|
NodeBasedEdge() { }
|
||||||
@@ -129,7 +133,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class EdgeT>
|
template<class EdgeT>
|
||||||
EdgeBasedEdge(const EdgeT & myEdge ) :
|
explicit EdgeBasedEdge(const EdgeT & myEdge ) :
|
||||||
m_source(myEdge.source),
|
m_source(myEdge.source),
|
||||||
m_target(myEdge.target),
|
m_target(myEdge.target),
|
||||||
m_edgeID(myEdge.data.via),
|
m_edgeID(myEdge.data.via),
|
||||||
@@ -162,7 +166,7 @@ public:
|
|||||||
m_weight(w),
|
m_weight(w),
|
||||||
m_forward(f),
|
m_forward(f),
|
||||||
m_backward(b)
|
m_backward(b)
|
||||||
{}
|
{ }
|
||||||
|
|
||||||
NodeID target() const { return m_target; }
|
NodeID target() const { return m_target; }
|
||||||
NodeID source() const { return m_source; }
|
NodeID source() const { return m_source; }
|
||||||
|
|||||||
@@ -44,11 +44,17 @@ struct ExternalMemoryNode : NodeInfo {
|
|||||||
bollard(bollard),
|
bollard(bollard),
|
||||||
trafficLight(traffic_light)
|
trafficLight(traffic_light)
|
||||||
{ }
|
{ }
|
||||||
ExternalMemoryNode() : bollard(false), trafficLight(false) {}
|
|
||||||
|
ExternalMemoryNode()
|
||||||
|
:
|
||||||
|
bollard(false),
|
||||||
|
trafficLight(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
static ExternalMemoryNode min_value() {
|
static ExternalMemoryNode min_value() {
|
||||||
return ExternalMemoryNode(0,0,0, false, false);
|
return ExternalMemoryNode(0,0,0, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ExternalMemoryNode max_value() {
|
static ExternalMemoryNode max_value() {
|
||||||
return ExternalMemoryNode(
|
return ExternalMemoryNode(
|
||||||
std::numeric_limits<int>::max(),
|
std::numeric_limits<int>::max(),
|
||||||
@@ -58,9 +64,11 @@ struct ExternalMemoryNode : NodeInfo {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID key() const {
|
NodeID key() const {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bollard;
|
bool bollard;
|
||||||
bool trafficLight;
|
bool trafficLight;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef INPUTREADERFACTORY_H
|
#ifndef INPUTREADERFACTORY_H
|
||||||
#define INPUTREADERFACTORY_H
|
#define INPUTREADERFACTORY_H
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <bzlib.h>
|
#include <bzlib.h>
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
|
||||||
@@ -51,21 +53,21 @@ int readFromBz2Stream( void* pointer, char* buffer, int len ) {
|
|||||||
return read;
|
return read;
|
||||||
} else if(BZ_STREAM_END == context->error) {
|
} else if(BZ_STREAM_END == context->error) {
|
||||||
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
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;
|
unusedTmp = (char*)unusedTmpVoid;
|
||||||
for(int i=0;i<context->nUnused;i++) {
|
for(int i=0;i<context->nUnused;i++) {
|
||||||
context->unused[i] = unusedTmp[i];
|
context->unused[i] = unusedTmp[i];
|
||||||
}
|
}
|
||||||
BZ2_bzReadClose(&context->error, context->bz2);
|
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
|
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
|
||||||
if(0 == context->nUnused && feof(context->file)) {
|
if(0 == context->nUnused && feof(context->file)) {
|
||||||
return read;
|
return read;
|
||||||
} else {
|
} else {
|
||||||
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
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;
|
return read;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ private:
|
|||||||
std::list<CacheEntry> itemsInCache;
|
std::list<CacheEntry> itemsInCache;
|
||||||
boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap;
|
boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap;
|
||||||
public:
|
public:
|
||||||
LRUCache(unsigned c) : capacity(c) {}
|
explicit LRUCache(unsigned c) : capacity(c) {}
|
||||||
|
|
||||||
bool Holds(KeyT key) {
|
bool Holds(KeyT key) {
|
||||||
if(positionMap.find(key) != positionMap.end()) {
|
if(positionMap.find(key) != positionMap.end()) {
|
||||||
|
|||||||
@@ -31,28 +31,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "TurnInstructions.h"
|
#include "TurnInstructions.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <limits>
|
||||||
|
|
||||||
struct OriginalEdgeData{
|
struct OriginalEdgeData{
|
||||||
explicit OriginalEdgeData(
|
explicit OriginalEdgeData(
|
||||||
NodeID via_node,
|
NodeID via_node,
|
||||||
unsigned name_id,
|
unsigned name_id,
|
||||||
TurnInstruction turn_instruction
|
TurnInstruction turn_instruction,
|
||||||
|
bool compressed_geometry
|
||||||
) :
|
) :
|
||||||
via_node(via_node),
|
via_node( via_node ),
|
||||||
name_id(name_id),
|
name_id( name_id ),
|
||||||
turn_instruction(turn_instruction)
|
turn_instruction( turn_instruction ),
|
||||||
|
compressed_geometry( compressed_geometry )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
OriginalEdgeData() :
|
OriginalEdgeData() :
|
||||||
via_node(UINT_MAX),
|
via_node( std::numeric_limits<unsigned>::max() ),
|
||||||
name_id(UINT_MAX),
|
name_id( std::numeric_limits<unsigned>::max() ),
|
||||||
turn_instruction(UCHAR_MAX)
|
turn_instruction( std::numeric_limits<unsigned char>::max() ),
|
||||||
|
compressed_geometry( false )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
NodeID via_node;
|
NodeID via_node;
|
||||||
unsigned name_id;
|
unsigned name_id;
|
||||||
TurnInstruction turn_instruction;
|
TurnInstruction turn_instruction;
|
||||||
|
bool compressed_geometry;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //ORIGINAL_EDGE_DATA_H
|
#endif //ORIGINAL_EDGE_DATA_H
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public:
|
|||||||
* @param maxValue the value that corresponds to 100%
|
* @param maxValue the value that corresponds to 100%
|
||||||
* @param step the progress is shown in steps of 'step' percent
|
* @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);
|
reinit(maxValue, step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+115
-45
@@ -29,75 +29,145 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define PHANTOMNODES_H_
|
#define PHANTOMNODES_H_
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
struct PhantomNode {
|
struct PhantomNode
|
||||||
|
{
|
||||||
PhantomNode() :
|
PhantomNode() :
|
||||||
edgeBasedNode(UINT_MAX),
|
forward_node_id(SPECIAL_NODEID),
|
||||||
nodeBasedEdgeNameID(UINT_MAX),
|
reverse_node_id(SPECIAL_NODEID),
|
||||||
weight1(INT_MAX),
|
name_id(std::numeric_limits<unsigned>::max()),
|
||||||
weight2(INT_MAX),
|
forward_weight(INVALID_EDGE_WEIGHT),
|
||||||
ratio(0.)
|
reverse_weight(INVALID_EDGE_WEIGHT),
|
||||||
|
forward_offset(0),
|
||||||
|
reverse_offset(0),
|
||||||
|
packed_geometry_id(SPECIAL_EDGEID),
|
||||||
|
fwd_segment_position(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
NodeID edgeBasedNode;
|
NodeID forward_node_id;
|
||||||
unsigned nodeBasedEdgeNameID;
|
NodeID reverse_node_id;
|
||||||
int weight1;
|
unsigned name_id;
|
||||||
int weight2;
|
int forward_weight;
|
||||||
double ratio;
|
int reverse_weight;
|
||||||
|
int forward_offset;
|
||||||
|
int reverse_offset;
|
||||||
|
unsigned packed_geometry_id;
|
||||||
FixedPointCoordinate location;
|
FixedPointCoordinate location;
|
||||||
void Reset() {
|
unsigned short fwd_segment_position;
|
||||||
edgeBasedNode = UINT_MAX;
|
|
||||||
nodeBasedEdgeNameID = UINT_MAX;
|
int GetForwardWeightPlusOffset() const
|
||||||
weight1 = INT_MAX;
|
{
|
||||||
weight2 = INT_MAX;
|
if (SPECIAL_NODEID == forward_node_id)
|
||||||
ratio = 0.;
|
{
|
||||||
location.Reset();
|
return 0;
|
||||||
}
|
}
|
||||||
bool isBidirected() const {
|
const int result = (forward_offset + forward_weight);
|
||||||
return weight2 != INT_MAX;
|
return result;
|
||||||
}
|
|
||||||
bool isValid(const unsigned numberOfNodes) const {
|
|
||||||
return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return location == other.location;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PhantomNodes {
|
struct PhantomNodes
|
||||||
PhantomNode startPhantom;
|
{
|
||||||
PhantomNode targetPhantom;
|
PhantomNode source_phantom;
|
||||||
void Reset() {
|
PhantomNode target_phantom;
|
||||||
startPhantom.Reset();
|
|
||||||
targetPhantom.Reset();
|
void Reset()
|
||||||
|
{
|
||||||
|
source_phantom.Reset();
|
||||||
|
target_phantom.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhantomsAreOnSameNodeBasedEdge() const {
|
bool PhantomsAreOnSameNodeBasedEdge() const
|
||||||
return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
|
{
|
||||||
|
return (source_phantom.forward_node_id == target_phantom.forward_node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AtLeastOnePhantomNodeIsUINTMAX() const {
|
bool AtLeastOnePhantomNodeIsInvalid() const
|
||||||
return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
|
{
|
||||||
|
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 {
|
bool PhantomNodesHaveEqualLocation() const
|
||||||
return startPhantom == targetPhantom;
|
{
|
||||||
|
return source_phantom == target_phantom;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
|
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 << "source_coord: " << pn.source_phantom.location << "\n";
|
||||||
out << "startCoord: " << pn.startPhantom.location << std::endl;
|
out << "target_coord: " << pn.target_phantom.location << std::endl;
|
||||||
out << "targetCoord: " << pn.targetPhantom.location << std::endl;
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
|
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;
|
{
|
||||||
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
struct QueryEdge {
|
struct QueryEdge {
|
||||||
NodeID source;
|
NodeID source;
|
||||||
NodeID target;
|
NodeID target;
|
||||||
|
|||||||
+14
-13
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _NODE_COORDS_H
|
#ifndef QUERY_NODE_H
|
||||||
#define _NODE_COORDS_H
|
#define QUERY_NODE_H
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
@@ -34,17 +34,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
struct NodeInfo {
|
struct NodeInfo {
|
||||||
typedef NodeID key_type; //type of NodeID
|
typedef NodeID key_type; //type of NodeID
|
||||||
typedef int value_type; //type of lat,lons
|
typedef int value_type; //type of lat,lons
|
||||||
|
|
||||||
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
|
NodeInfo(int lat, int lon, NodeID id) : lat(lat), lon(lon), id(id) { }
|
||||||
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
|
NodeInfo()
|
||||||
|
:
|
||||||
|
lat(std::numeric_limits<int>::max()),
|
||||||
|
lon(std::numeric_limits<int>::max()),
|
||||||
|
id(std::numeric_limits<unsigned>::max())
|
||||||
|
{ }
|
||||||
|
|
||||||
int lat;
|
int lat;
|
||||||
int lon;
|
int lon;
|
||||||
NodeID id;
|
NodeID id;
|
||||||
@@ -69,18 +72,16 @@ struct NodeInfo {
|
|||||||
switch(n) {
|
switch(n) {
|
||||||
case 1:
|
case 1:
|
||||||
return lat;
|
return lat;
|
||||||
break;
|
// break;
|
||||||
case 0:
|
case 0:
|
||||||
return lon;
|
return lon;
|
||||||
break;
|
// break;
|
||||||
default:
|
default:
|
||||||
BOOST_ASSERT_MSG(false, "should not happen");
|
|
||||||
return UINT_MAX;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT_MSG(false, "should not happen");
|
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;
|
unsigned checkSum;
|
||||||
int lengthOfShortestPath;
|
int lengthOfShortestPath;
|
||||||
int lengthOfAlternativePath;
|
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() :
|
RawRouteData() :
|
||||||
checkSum(UINT_MAX),
|
checkSum(UINT_MAX),
|
||||||
lengthOfShortestPath(INT_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_
|
#define RESTRICTION_H_
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include <climits>
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
struct TurnRestriction {
|
struct TurnRestriction {
|
||||||
NodeID viaNode;
|
NodeID viaNode;
|
||||||
@@ -58,14 +59,13 @@ struct TurnRestriction {
|
|||||||
bool unused7:1;
|
bool unused7:1;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
TurnRestriction(NodeID viaNode) :
|
explicit TurnRestriction(NodeID viaNode) :
|
||||||
viaNode(viaNode),
|
viaNode(viaNode),
|
||||||
fromNode(UINT_MAX),
|
fromNode(std::numeric_limits<unsigned>::max()),
|
||||||
toNode(UINT_MAX) {
|
toNode(std::numeric_limits<unsigned>::max()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TurnRestriction(const bool isOnly = false) :
|
explicit TurnRestriction(const bool isOnly = false) :
|
||||||
viaNode(UINT_MAX),
|
viaNode(UINT_MAX),
|
||||||
fromNode(UINT_MAX),
|
fromNode(UINT_MAX),
|
||||||
toNode(UINT_MAX) {
|
toNode(UINT_MAX) {
|
||||||
@@ -91,12 +91,12 @@ struct InputRestrictionContainer {
|
|||||||
{
|
{
|
||||||
restriction.viaNode = vn;
|
restriction.viaNode = vn;
|
||||||
}
|
}
|
||||||
InputRestrictionContainer(
|
explicit InputRestrictionContainer(
|
||||||
bool isOnly = false
|
bool isOnly = false
|
||||||
) :
|
) :
|
||||||
fromWay(UINT_MAX),
|
fromWay(std::numeric_limits<unsigned>::max()),
|
||||||
toWay(UINT_MAX),
|
toWay(std::numeric_limits<unsigned>::max()),
|
||||||
viaNode(UINT_MAX)
|
viaNode(std::numeric_limits<unsigned>::max())
|
||||||
{
|
{
|
||||||
restriction.flags.isOnly = isOnly;
|
restriction.flags.isOnly = isOnly;
|
||||||
}
|
}
|
||||||
@@ -106,10 +106,10 @@ struct InputRestrictionContainer {
|
|||||||
}
|
}
|
||||||
static InputRestrictionContainer max_value() {
|
static InputRestrictionContainer max_value() {
|
||||||
return InputRestrictionContainer(
|
return InputRestrictionContainer(
|
||||||
UINT_MAX,
|
std::numeric_limits<unsigned>::max(),
|
||||||
UINT_MAX,
|
std::numeric_limits<unsigned>::max(),
|
||||||
UINT_MAX,
|
std::numeric_limits<unsigned>::max(),
|
||||||
UINT_MAX
|
std::numeric_limits<unsigned>::max()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
ShortestPathRouting<DataFacadeT> shortest_path;
|
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||||
AlternativeRouting <DataFacadeT> alternative_path;
|
AlternativeRouting <DataFacadeT> alternative_path;
|
||||||
|
|
||||||
SearchEngine( DataFacadeT * facade )
|
explicit SearchEngine( DataFacadeT * facade )
|
||||||
:
|
:
|
||||||
facade (facade),
|
facade (facade),
|
||||||
shortest_path (facade, engine_working_data),
|
shortest_path (facade, engine_working_data),
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
struct _HeapData {
|
struct _HeapData {
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
_HeapData( NodeID p ) : parent(p) { }
|
/* explicit */ _HeapData( NodeID p ) : parent(p) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ template<typename DataT>
|
|||||||
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
|
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
|
||||||
DataT * p;
|
DataT * p;
|
||||||
public:
|
public:
|
||||||
ShMemIterator(DataT * x) : p(x) {}
|
explicit ShMemIterator(DataT * x) : p(x) {}
|
||||||
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {}
|
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {}
|
||||||
ShMemIterator& operator++() {
|
ShMemIterator& operator++() {
|
||||||
++p;
|
++p;
|
||||||
@@ -115,6 +115,8 @@ public:
|
|||||||
|
|
||||||
std::size_t size() const { return m_size; }
|
std::size_t size() const { return m_size; }
|
||||||
|
|
||||||
|
bool empty() const { return 0 == size(); }
|
||||||
|
|
||||||
DataT & operator[](const unsigned index) {
|
DataT & operator[](const unsigned index) {
|
||||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
return m_ptr[index];
|
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>
|
template<typename DataT, bool UseSharedMemory>
|
||||||
struct ShM {
|
struct ShM {
|
||||||
typedef typename boost::conditional<
|
typedef typename boost::conditional<
|
||||||
@@ -135,5 +194,4 @@ struct ShM {
|
|||||||
>::type vector;
|
>::type vector;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H
|
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
|
|||||||
@@ -112,16 +112,18 @@ public:
|
|||||||
if(eid2 == UINT_MAX) {
|
if(eid2 == UINT_MAX) {
|
||||||
SimpleLogger().Write(logWARNING) <<
|
SimpleLogger().Write(logWARNING) <<
|
||||||
"cannot find first segment of edge (" <<
|
"cannot find first segment of edge (" <<
|
||||||
u << "," << data.id << "," << v << ")";
|
u << "," << data.id << "," << v << "), eid: " << eid;
|
||||||
|
|
||||||
data.shortcut = false;
|
data.shortcut = false;
|
||||||
|
BOOST_ASSERT(false);
|
||||||
}
|
}
|
||||||
eid2 = FindEdgeInEitherDirection(data.id, v);
|
eid2 = FindEdgeInEitherDirection(data.id, v);
|
||||||
if(eid2 == UINT_MAX) {
|
if(eid2 == UINT_MAX) {
|
||||||
SimpleLogger().Write(logWARNING) <<
|
SimpleLogger().Write(logWARNING) <<
|
||||||
"cannot find second segment of edge (" <<
|
"cannot find second segment of edge (" <<
|
||||||
u << "," << data.id << "," << v << ")";
|
u << "," << data.id << "," << v << "), eid2: " << eid2;
|
||||||
data.shortcut = false;
|
data.shortcut = false;
|
||||||
|
BOOST_ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,17 +157,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
||||||
return EdgeIterator( _nodes[n].firstEdge );
|
return EdgeIterator( _nodes.at(n).firstEdge );
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator EndEdges( const NodeIterator n ) const {
|
EdgeIterator EndEdges( const NodeIterator n ) const {
|
||||||
return EdgeIterator( _nodes[n+1].firstEdge );
|
return EdgeIterator( _nodes.at(n+1).firstEdge );
|
||||||
}
|
}
|
||||||
|
|
||||||
//searches for a specific edge
|
//searches for a specific edge
|
||||||
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
||||||
EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
||||||
EdgeWeight smallestWeight = UINT_MAX;
|
EdgeWeight smallestWeight = INVALID_EDGE_WEIGHT;
|
||||||
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
||||||
const NodeID target = GetTarget(edge);
|
const NodeID target = GetTarget(edge);
|
||||||
const EdgeWeight weight = GetEdgeData(edge).distance;
|
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( k > 0 );
|
||||||
BOOST_ASSERT ( points->size() > 0 );
|
BOOST_ASSERT ( points->size() > 0 );
|
||||||
size = points->size();
|
size = points->size();
|
||||||
@@ -207,7 +207,7 @@ private:
|
|||||||
};
|
};
|
||||||
class Less {
|
class Less {
|
||||||
public:
|
public:
|
||||||
Less( unsigned d ) {
|
explicit Less( unsigned d ) {
|
||||||
dimension = d;
|
dimension = d;
|
||||||
BOOST_ASSERT( dimension < k );
|
BOOST_ASSERT( dimension < k );
|
||||||
}
|
}
|
||||||
|
|||||||
+101
-210
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "DeallocatingVector.h"
|
#include "DeallocatingVector.h"
|
||||||
#include "HilbertValue.h"
|
#include "HilbertValue.h"
|
||||||
#include "PhantomNodes.h"
|
#include "PhantomNodes.h"
|
||||||
|
#include "QueryNode.h"
|
||||||
#include "SharedMemoryFactory.h"
|
#include "SharedMemoryFactory.h"
|
||||||
#include "SharedMemoryVectorWrapper.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/algorithm/minmax_element.hpp>
|
||||||
#include <boost/range/algorithm_ext/erase.hpp>
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include <boost/type_traits.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;
|
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 {
|
class StaticRTree : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
struct RectangleInt2D {
|
struct RectangleInt2D {
|
||||||
@@ -82,22 +84,35 @@ public:
|
|||||||
int32_t min_lat, max_lat;
|
int32_t min_lat, max_lat;
|
||||||
|
|
||||||
inline void InitializeMBRectangle(
|
inline void InitializeMBRectangle(
|
||||||
const DataT * objects,
|
DataT const * objects,
|
||||||
const uint32_t element_count
|
const uint32_t element_count,
|
||||||
|
const std::vector<NodeInfo> & coordinate_list
|
||||||
) {
|
) {
|
||||||
for(uint32_t i = 0; i < element_count; ++i) {
|
for(uint32_t i = 0; i < element_count; ++i) {
|
||||||
min_lon = std::min(
|
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(
|
||||||
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(
|
||||||
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).lat
|
||||||
|
)
|
||||||
);
|
);
|
||||||
max_lat = std::max(
|
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).lat
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,9 +236,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool Contains(const FixedPointCoordinate & location) const {
|
inline bool Contains(const FixedPointCoordinate & location) const {
|
||||||
bool lats_contained =
|
const bool lats_contained =
|
||||||
(location.lat > min_lat) && (location.lat < max_lat);
|
(location.lat > min_lat) && (location.lat < max_lat);
|
||||||
bool lons_contained =
|
const bool lons_contained =
|
||||||
(location.lon > min_lon) && (location.lon < max_lon);
|
(location.lon > min_lon) && (location.lon < max_lon);
|
||||||
return lats_contained && lons_contained;
|
return lats_contained && lons_contained;
|
||||||
}
|
}
|
||||||
@@ -289,21 +304,23 @@ private:
|
|||||||
|
|
||||||
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
|
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
|
||||||
uint64_t m_element_count;
|
uint64_t m_element_count;
|
||||||
|
|
||||||
const std::string m_leaf_node_filename;
|
const std::string m_leaf_node_filename;
|
||||||
|
boost::shared_ptr<CoordinateListT> m_coordinate_list;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
|
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
|
||||||
explicit StaticRTree(
|
explicit StaticRTree(
|
||||||
std::vector<DataT> & input_data_vector,
|
std::vector<DataT> & input_data_vector,
|
||||||
const std::string tree_node_filename,
|
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_element_count(input_data_vector.size()),
|
||||||
m_leaf_node_filename(leaf_node_filename)
|
m_leaf_node_filename(leaf_node_filename)
|
||||||
{
|
{
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() <<
|
||||||
"constructing r-tree of " << m_element_count <<
|
"constructing r-tree of " << m_element_count <<
|
||||||
" elements";
|
" edge elements build on-top of " << coordinate_list.size() << " coordinates";
|
||||||
|
|
||||||
double time1 = get_timestamp();
|
double time1 = get_timestamp();
|
||||||
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
|
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) {
|
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
|
||||||
input_wrapper_vector[element_counter].m_array_index = element_counter;
|
input_wrapper_vector[element_counter].m_array_index = element_counter;
|
||||||
//Get Hilbert-Value for centroid in mercartor projection
|
//Get Hilbert-Value for centroid in mercartor projection
|
||||||
DataT & current_element = input_data_vector[element_counter];
|
DataT const & current_element = input_data_vector[element_counter];
|
||||||
FixedPointCoordinate current_centroid = current_element.Centroid();
|
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);
|
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
|
||||||
|
|
||||||
uint64_t current_hilbert_value = get_hilbert_number(current_centroid);
|
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
|
//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.child_is_on_disk = true;
|
||||||
current_node.children[0] = tree_nodes_in_level.size();
|
current_node.children[0] = tree_nodes_in_level.size();
|
||||||
tree_nodes_in_level.push_back(current_node);
|
tree_nodes_in_level.push_back(current_node);
|
||||||
@@ -426,9 +456,11 @@ public:
|
|||||||
//Read-only operation for queries
|
//Read-only operation for queries
|
||||||
explicit StaticRTree(
|
explicit StaticRTree(
|
||||||
const boost::filesystem::path & node_file,
|
const boost::filesystem::path & node_file,
|
||||||
const boost::filesystem::path & leaf_file
|
const boost::filesystem::path & leaf_file,
|
||||||
) : m_leaf_node_filename(leaf_file.string()) {
|
const boost::shared_ptr<CoordinateListT> coordinate_list
|
||||||
|
) : m_leaf_node_filename( leaf_file.string() ) {
|
||||||
//open tree node file and load into RAM.
|
//open tree node file and load into RAM.
|
||||||
|
m_coordinate_list = coordinate_list;
|
||||||
|
|
||||||
if ( !boost::filesystem::exists( node_file ) ) {
|
if ( !boost::filesystem::exists( node_file ) ) {
|
||||||
throw OSRMException("ram index file does not exist");
|
throw OSRMException("ram index file does not exist");
|
||||||
@@ -463,9 +495,11 @@ public:
|
|||||||
explicit StaticRTree(
|
explicit StaticRTree(
|
||||||
TreeNode * tree_node_ptr,
|
TreeNode * tree_node_ptr,
|
||||||
const uint32_t number_of_nodes,
|
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_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
|
//open leaf node file and store thread specific pointer
|
||||||
if ( !boost::filesystem::exists( leaf_file ) ) {
|
if ( !boost::filesystem::exists( leaf_file ) ) {
|
||||||
@@ -487,152 +521,7 @@ public:
|
|||||||
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||||
}
|
}
|
||||||
//Read-only operation for queries
|
//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(
|
bool LocateClosestEndPointForCoordinate(
|
||||||
const FixedPointCoordinate & input_coordinate,
|
const FixedPointCoordinate & input_coordinate,
|
||||||
FixedPointCoordinate & result_coordinate,
|
FixedPointCoordinate & result_coordinate,
|
||||||
@@ -671,7 +560,7 @@ public:
|
|||||||
current_leaf_node
|
current_leaf_node
|
||||||
);
|
);
|
||||||
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
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(
|
if(
|
||||||
ignore_tiny_components &&
|
ignore_tiny_components &&
|
||||||
current_edge.belongsToTinyComponent
|
current_edge.belongsToTinyComponent
|
||||||
@@ -682,29 +571,29 @@ public:
|
|||||||
double current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
double current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||||
input_coordinate.lat,
|
input_coordinate.lat,
|
||||||
input_coordinate.lon,
|
input_coordinate.lon,
|
||||||
current_edge.lat1,
|
m_coordinate_list->at(current_edge.u).lat,
|
||||||
current_edge.lon1
|
m_coordinate_list->at(current_edge.u).lon
|
||||||
);
|
);
|
||||||
if( current_minimum_distance < min_dist ) {
|
if( current_minimum_distance < min_dist ) {
|
||||||
//found a new minimum
|
//found a new minimum
|
||||||
min_dist = current_minimum_distance;
|
min_dist = current_minimum_distance;
|
||||||
result_coordinate.lat = current_edge.lat1;
|
result_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
|
||||||
result_coordinate.lon = current_edge.lon1;
|
result_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
|
||||||
found_a_nearest_edge = true;
|
found_a_nearest_edge = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||||
input_coordinate.lat,
|
input_coordinate.lat,
|
||||||
input_coordinate.lon,
|
input_coordinate.lon,
|
||||||
current_edge.lat2,
|
m_coordinate_list->at(current_edge.v).lat,
|
||||||
current_edge.lon2
|
m_coordinate_list->at(current_edge.v).lon
|
||||||
);
|
);
|
||||||
|
|
||||||
if( current_minimum_distance < min_dist ) {
|
if( current_minimum_distance < min_dist ) {
|
||||||
//found a new minimum
|
//found a new minimum
|
||||||
min_dist = current_minimum_distance;
|
min_dist = current_minimum_distance;
|
||||||
result_coordinate.lat = current_edge.lat2;
|
result_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
|
||||||
result_coordinate.lon = current_edge.lon2;
|
result_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
|
||||||
found_a_nearest_edge = true;
|
found_a_nearest_edge = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -783,7 +672,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
double current_ratio = 0.;
|
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,
|
input_coordinate,
|
||||||
nearest,
|
nearest,
|
||||||
current_ratio
|
current_ratio
|
||||||
@@ -799,41 +690,24 @@ public:
|
|||||||
)
|
)
|
||||||
) { //found a new minimum
|
) { //found a new minimum
|
||||||
min_dist = current_perpendicular_distance;
|
min_dist = current_perpendicular_distance;
|
||||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
//TODO: use assignment c'tor in PhantomNode
|
||||||
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
result_phantom_node.forward_node_id = current_edge.forward_edge_based_node_id;
|
||||||
result_phantom_node.weight1 = current_edge.weight;
|
result_phantom_node.reverse_node_id = current_edge.reverse_edge_based_node_id;
|
||||||
result_phantom_node.weight2 = INT_MAX;
|
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;
|
result_phantom_node.location = nearest;
|
||||||
current_start_coordinate.lat = current_edge.lat1;
|
current_start_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
|
||||||
current_start_coordinate.lon = current_edge.lon1;
|
current_start_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
|
||||||
current_end_coordinate.lat = current_edge.lat2;
|
current_end_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
|
||||||
current_end_coordinate.lon = current_edge.lon2;
|
current_end_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
|
||||||
nearest_edge = current_edge;
|
nearest_edge = current_edge;
|
||||||
found_a_nearest_edge = true;
|
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 {
|
} else {
|
||||||
@@ -884,11 +758,28 @@ public:
|
|||||||
ratio = std::min(1., ratio);
|
ratio = std::min(1., ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
result_phantom_node.weight1 *= ratio;
|
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_offset: " << result_phantom_node.forward_offset;
|
||||||
if(INT_MAX != result_phantom_node.weight2) {
|
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_offset: " << result_phantom_node.reverse_offset;
|
||||||
result_phantom_node.weight2 *= (1.-ratio);
|
// 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;
|
return found_a_nearest_edge;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,4 @@ struct TurnInstructionsClass : boost::noncopyable {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static TurnInstructionsClass TurnInstructions;
|
|
||||||
|
|
||||||
#endif /* TURNINSTRUCTIONS_H_ */
|
#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 ) {
|
inline HashCell& operator[]( const NodeID node ) {
|
||||||
unsigned short position = fastHash(node);
|
unsigned short position = fastHash(node);
|
||||||
|
|||||||
@@ -31,18 +31,18 @@ DescriptionFactory::DescriptionFactory() : entireLength(0) { }
|
|||||||
|
|
||||||
DescriptionFactory::~DescriptionFactory() { }
|
DescriptionFactory::~DescriptionFactory() { }
|
||||||
|
|
||||||
inline double DescriptionFactory::DegreeToRadian(const double degree) const {
|
inline double DescriptionFactory::DegreeToRadian(const double degree) const
|
||||||
return degree * (M_PI/180);
|
{
|
||||||
|
return degree * (M_PI/180.);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double DescriptionFactory::RadianToDegree(const double radian) const {
|
inline double DescriptionFactory::RadianToDegree(const double radian) const
|
||||||
return radian * (180/M_PI);
|
{
|
||||||
|
return radian * (180./M_PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
double DescriptionFactory::GetBearing(
|
double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const FixedPointCoordinate & B) const
|
||||||
const FixedPointCoordinate & A,
|
{
|
||||||
const FixedPointCoordinate & B
|
|
||||||
) const {
|
|
||||||
double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
||||||
|
|
||||||
const double lat1 = DegreeToRadian(A.lat/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 y = sin(delta_long) * cos(lat2);
|
||||||
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
|
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
|
||||||
double result = RadianToDegree(atan2(y, x));
|
double result = RadianToDegree(atan2(y, x));
|
||||||
while(result < 0.) {
|
while (result < 0.)
|
||||||
|
{
|
||||||
result += 360.;
|
result += 360.;
|
||||||
}
|
}
|
||||||
while(result >= 360.) {
|
|
||||||
|
while (result >= 360.)
|
||||||
|
{
|
||||||
result -= 360.;
|
result -= 360.;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::SetStartSegment(const PhantomNode & start) {
|
void DescriptionFactory::SetStartSegment(const PhantomNode & source, const bool source_traversed_in_reverse)
|
||||||
start_phantom = start;
|
{
|
||||||
|
start_phantom = source;
|
||||||
AppendSegment(
|
AppendSegment(
|
||||||
start.location,
|
source.location,
|
||||||
PathData(0, start.nodeBasedEdgeNameID, 10, start.weight1)
|
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;
|
target_phantom = target;
|
||||||
pathDescription.push_back(
|
pathDescription.push_back(
|
||||||
SegmentInformation(
|
SegmentInformation(
|
||||||
target.location,
|
target.location,
|
||||||
target.nodeBasedEdgeNameID,
|
target.name_id,
|
||||||
0,
|
0,
|
||||||
target.weight1,
|
target.reverse_weight,
|
||||||
0,
|
0,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendSegment(
|
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const PathData & path_point)
|
||||||
const FixedPointCoordinate & coordinate,
|
{
|
||||||
const PathData & data
|
if ((1 == pathDescription.size()) && ( pathDescription.back().location == coordinate))
|
||||||
) {
|
{
|
||||||
if(
|
pathDescription.back().name_id = path_point.name_id;
|
||||||
( 1 == pathDescription.size()) &&
|
}
|
||||||
( pathDescription.back().location == coordinate)
|
else
|
||||||
) {
|
{
|
||||||
pathDescription.back().name_id = data.name_id;
|
|
||||||
} else {
|
|
||||||
pathDescription.push_back(
|
pathDescription.push_back(
|
||||||
SegmentInformation(
|
SegmentInformation(coordinate, path_point.name_id, path_point.durationOfSegment, 0, path_point.turnInstruction)
|
||||||
coordinate,
|
|
||||||
data.name_id,
|
|
||||||
data.durationOfSegment,
|
|
||||||
0,
|
|
||||||
data.turnInstruction
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +134,7 @@ void DescriptionFactory::BuildRouteSummary(
|
|||||||
const double distance,
|
const double distance,
|
||||||
const unsigned time
|
const unsigned time
|
||||||
) {
|
) {
|
||||||
summary.startName = start_phantom.nodeBasedEdgeNameID;
|
summary.startName = start_phantom.name_id;
|
||||||
summary.destName = target_phantom.nodeBasedEdgeNameID;
|
summary.destName = target_phantom.name_id;
|
||||||
summary.BuildDurationAndLengthStrings(distance, time);
|
summary.BuildDurationAndLengthStrings(distance, time);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
) {
|
) {
|
||||||
//compute distance/duration for route summary
|
//compute distance/duration for route summary
|
||||||
intToString(round(distance), lengthString);
|
intToString(round(distance), lengthString);
|
||||||
int travel_time = time/10;
|
int travel_time = round(time/10.);
|
||||||
intToString(std::max(travel_time, 1), durationString);
|
intToString(std::max(travel_time, 1), durationString);
|
||||||
}
|
}
|
||||||
} summary;
|
} summary;
|
||||||
@@ -87,8 +87,8 @@ public:
|
|||||||
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
||||||
void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data);
|
void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data);
|
||||||
void BuildRouteSummary(const double distance, const unsigned time);
|
void BuildRouteSummary(const double distance, const unsigned time);
|
||||||
void SetStartSegment(const PhantomNode & start_phantom);
|
void SetStartSegment(const PhantomNode & start_phantom, const bool source_traversed_in_reverse);
|
||||||
void SetEndSegment(const PhantomNode & start_phantom);
|
void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse);
|
||||||
void AppendEncodedPolylineString(
|
void AppendEncodedPolylineString(
|
||||||
const bool return_encoded,
|
const bool return_encoded,
|
||||||
std::vector<std::string> & output
|
std::vector<std::string> & output
|
||||||
@@ -105,14 +105,13 @@ public:
|
|||||||
|
|
||||||
/** starts at index 1 */
|
/** starts at index 1 */
|
||||||
pathDescription[0].length = 0;
|
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);
|
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
|
/*Simplify turn instructions
|
||||||
Input :
|
Input :
|
||||||
10. Turn left on B 36 for 20 km
|
10. Turn left on B 36 for 20 km
|
||||||
@@ -154,23 +153,23 @@ public:
|
|||||||
// string0 = string1;
|
// string0 = string1;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
double lengthOfSegment = 0;
|
double segment_length = 0.;
|
||||||
unsigned durationOfSegment = 0;
|
unsigned segment_duration = 0;
|
||||||
unsigned indexOfSegmentBegin = 0;
|
unsigned segment_start_index = 0;
|
||||||
|
|
||||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
entireLength += pathDescription[i].length;
|
entireLength += pathDescription[i].length;
|
||||||
lengthOfSegment += pathDescription[i].length;
|
segment_length += pathDescription[i].length;
|
||||||
durationOfSegment += pathDescription[i].duration;
|
segment_duration += pathDescription[i].duration;
|
||||||
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
pathDescription[segment_start_index].length = segment_length;
|
||||||
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
pathDescription[segment_start_index].duration = segment_duration;
|
||||||
|
|
||||||
|
|
||||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
|
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
|
||||||
BOOST_ASSERT(pathDescription[i].necessary);
|
BOOST_ASSERT(pathDescription[i].necessary);
|
||||||
lengthOfSegment = 0;
|
segment_length = 0;
|
||||||
durationOfSegment = 0;
|
segment_duration = 0;
|
||||||
indexOfSegmentBegin = i;
|
segment_start_index = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,21 +178,17 @@ public:
|
|||||||
if(pathDescription.size() > 2){
|
if(pathDescription.size() > 2){
|
||||||
pathDescription.pop_back();
|
pathDescription.pop_back();
|
||||||
pathDescription.back().necessary = true;
|
pathDescription.back().necessary = true;
|
||||||
pathDescription.back().turn_instruction = TurnInstructions.NoTurn;
|
pathDescription.back().turn_instruction = TurnInstructionsClass::NoTurn;
|
||||||
target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->name_id;
|
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(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
|
||||||
if(pathDescription.size() > 2) {
|
if(pathDescription.size() > 2) {
|
||||||
pathDescription.erase(pathDescription.begin());
|
pathDescription.erase(pathDescription.begin());
|
||||||
pathDescription[0].turn_instruction = TurnInstructions.HeadOn;
|
pathDescription[0].turn_instruction = TurnInstructionsClass::HeadOn;
|
||||||
pathDescription[0].necessary = true;
|
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
|
//Generalize poly line
|
||||||
|
|||||||
@@ -65,12 +65,12 @@ public:
|
|||||||
(raw_route.unpacked_path_segments[0].size());
|
(raw_route.unpacked_path_segments[0].size());
|
||||||
if( found_route ) {
|
if( found_route ) {
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(
|
FixedPointCoordinate::convertInternalLatLonToString(
|
||||||
phantom_node_list.startPhantom.location.lat,
|
phantom_node_list.source_phantom.location.lat,
|
||||||
tmp
|
tmp
|
||||||
);
|
);
|
||||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(
|
FixedPointCoordinate::convertInternalLatLonToString(
|
||||||
phantom_node_list.startPhantom.location.lon,
|
phantom_node_list.source_phantom.location.lon,
|
||||||
tmp
|
tmp
|
||||||
);
|
);
|
||||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||||
@@ -90,12 +90,12 @@ public:
|
|||||||
}
|
}
|
||||||
// Add the via point or the end coordinate
|
// Add the via point or the end coordinate
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(
|
FixedPointCoordinate::convertInternalLatLonToString(
|
||||||
phantom_node_list.targetPhantom.location.lat,
|
phantom_node_list.target_phantom.location.lat,
|
||||||
tmp
|
tmp
|
||||||
);
|
);
|
||||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(
|
FixedPointCoordinate::convertInternalLatLonToString(
|
||||||
phantom_node_list.targetPhantom.location.lon,
|
phantom_node_list.target_phantom.location.lon,
|
||||||
tmp
|
tmp
|
||||||
);
|
);
|
||||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
template<class DataFacadeT>
|
template<class DataFacadeT>
|
||||||
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
|
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
|
||||||
private:
|
private:
|
||||||
|
// TODO: initalize in c'tor
|
||||||
DataFacadeT * facade;
|
DataFacadeT * facade;
|
||||||
DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
DescriptionFactory description_factory;
|
DescriptionFactory description_factory;
|
||||||
@@ -59,7 +60,7 @@ private:
|
|||||||
int start_index;
|
int start_index;
|
||||||
int name_id;
|
int name_id;
|
||||||
int leave_at_exit;
|
int leave_at_exit;
|
||||||
} roundAbout;
|
} round_about;
|
||||||
|
|
||||||
struct Segment {
|
struct Segment {
|
||||||
Segment() : name_id(-1), length(-1), position(-1) {}
|
Segment() : name_id(-1), length(-1), position(-1) {}
|
||||||
@@ -90,7 +91,7 @@ public:
|
|||||||
void SetConfig(const DescriptorConfig & c) { config = c; }
|
void SetConfig(const DescriptorConfig & c) { config = c; }
|
||||||
|
|
||||||
int DescribeLeg(
|
int DescribeLeg(
|
||||||
const std::vector<PathData> & route_leg,
|
const std::vector<PathData> route_leg,
|
||||||
const PhantomNodes & leg_phantoms
|
const PhantomNodes & leg_phantoms
|
||||||
) {
|
) {
|
||||||
int added_element_count = 0;
|
int added_element_count = 0;
|
||||||
@@ -98,10 +99,10 @@ public:
|
|||||||
FixedPointCoordinate current_coordinate;
|
FixedPointCoordinate current_coordinate;
|
||||||
BOOST_FOREACH(const PathData & path_data, route_leg) {
|
BOOST_FOREACH(const PathData & path_data, route_leg) {
|
||||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||||
description_factory.AppendSegment(current_coordinate, path_data );
|
description_factory.AppendSegment(current_coordinate, path_data);
|
||||||
++added_element_count;
|
++added_element_count;
|
||||||
}
|
}
|
||||||
// description_factory.SetEndSegment( leg_phantoms.targetPhantom );
|
// description_factory.SetEndSegment( leg_phantoms.target_phantom );
|
||||||
++added_element_count;
|
++added_element_count;
|
||||||
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count );
|
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count );
|
||||||
return added_element_count;
|
return added_element_count;
|
||||||
@@ -119,7 +120,8 @@ public:
|
|||||||
"{\"status\":"
|
"{\"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 ;-)
|
//We do not need to do much, if there is no route ;-)
|
||||||
reply.content.push_back(
|
reply.content.push_back(
|
||||||
"207,\"status_message\": \"Cannot find route between points\"}"
|
"207,\"status_message\": \"Cannot find route between points\"}"
|
||||||
@@ -127,12 +129,36 @@ public:
|
|||||||
return;
|
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,"
|
reply.content.push_back("0,"
|
||||||
"\"status_message\": \"Found route between points\",");
|
"\"status_message\": \"Found route between points\",");
|
||||||
|
|
||||||
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
|
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(
|
const int added_segments = DescribeLeg(
|
||||||
raw_route.unpacked_path_segments[i],
|
raw_route.unpacked_path_segments[i],
|
||||||
raw_route.segmentEndCoordinates[i]
|
raw_route.segmentEndCoordinates[i]
|
||||||
@@ -142,7 +168,7 @@ public:
|
|||||||
added_segments + shortest_leg_end_indices.back()
|
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);
|
description_factory.Run(facade, config.zoom_level);
|
||||||
|
|
||||||
reply.content.push_back("\"route_geometry\": ");
|
reply.content.push_back("\"route_geometry\": ");
|
||||||
@@ -194,14 +220,15 @@ public:
|
|||||||
|
|
||||||
//only one alternative route is computed at this time, so this is hardcoded
|
//only one alternative route is computed at this time, so this is hardcoded
|
||||||
|
|
||||||
if(raw_route.lengthOfAlternativePath != INT_MAX) {
|
if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT)
|
||||||
alternate_descriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
|
{
|
||||||
|
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse);
|
||||||
//Get all the coordinates for the computed route
|
//Get all the coordinates for the computed route
|
||||||
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) {
|
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) {
|
||||||
current = facade->GetCoordinateOfNode(path_data.node);
|
current = facade->GetCoordinateOfNode(path_data.node);
|
||||||
alternate_descriptionFactory.AppendSegment(current, path_data );
|
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);
|
alternate_descriptionFactory.Run(facade, config.zoom_level);
|
||||||
|
|
||||||
@@ -286,7 +313,7 @@ public:
|
|||||||
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||||
raw_route.segmentEndCoordinates.front().startPhantom.location,
|
raw_route.segmentEndCoordinates.front().source_phantom.location,
|
||||||
tmp
|
tmp
|
||||||
);
|
);
|
||||||
reply.content.push_back("[");
|
reply.content.push_back("[");
|
||||||
@@ -296,7 +323,7 @@ public:
|
|||||||
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) {
|
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) {
|
||||||
tmp.clear();
|
tmp.clear();
|
||||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||||
nodes.targetPhantom.location,
|
nodes.target_phantom.location,
|
||||||
tmp
|
tmp
|
||||||
);
|
);
|
||||||
reply.content.push_back(",[");
|
reply.content.push_back(",[");
|
||||||
@@ -332,11 +359,11 @@ public:
|
|||||||
std::string hint;
|
std::string hint;
|
||||||
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) {
|
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) {
|
||||||
reply.content.push_back("\"");
|
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(hint);
|
||||||
reply.content.push_back("\", ");
|
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("\"");
|
||||||
reply.content.push_back(hint);
|
reply.content.push_back(hint);
|
||||||
reply.content.push_back("\"]");
|
reply.content.push_back("\"]");
|
||||||
@@ -419,56 +446,61 @@ public:
|
|||||||
//Segment information has following format:
|
//Segment information has following format:
|
||||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||||
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
unsigned necessary_segments_running_index = 0;
|
||||||
unsigned prefixSumOfNecessarySegments = 0;
|
round_about.leave_at_exit = 0;
|
||||||
roundAbout.leave_at_exit = 0;
|
round_about.name_id = 0;
|
||||||
roundAbout.name_id = 0;
|
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||||
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
|
||||||
//Fetch data from Factory and generate a string from it.
|
//Fetch data from Factory and generate a string from it.
|
||||||
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
|
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);
|
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||||
if(TurnInstructions.TurnIsNecessary( current_instruction) ) {
|
if (TurnInstructionsClass::TurnIsNecessary( current_instruction) )
|
||||||
if(TurnInstructions.EnterRoundAbout == current_instruction) {
|
{
|
||||||
roundAbout.name_id = segment.name_id;
|
if (TurnInstructionsClass::EnterRoundAbout == current_instruction)
|
||||||
roundAbout.start_index = prefixSumOfNecessarySegments;
|
{
|
||||||
} else {
|
round_about.name_id = segment.name_id;
|
||||||
if(0 != prefixSumOfNecessarySegments){
|
round_about.start_index = necessary_segments_running_index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (0 != necessary_segments_running_index)
|
||||||
|
{
|
||||||
reply.content.push_back(",");
|
reply.content.push_back(",");
|
||||||
}
|
}
|
||||||
reply.content.push_back("[\"");
|
reply.content.push_back("[\"");
|
||||||
if(TurnInstructions.LeaveRoundAbout == current_instruction) {
|
if(TurnInstructionsClass::LeaveRoundAbout == current_instruction) {
|
||||||
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
|
intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction);
|
||||||
reply.content.push_back(tmpInstruction);
|
reply.content.push_back(temp_instruction);
|
||||||
reply.content.push_back("-");
|
reply.content.push_back("-");
|
||||||
intToString(roundAbout.leave_at_exit+1, tmpInstruction);
|
intToString(round_about.leave_at_exit+1, temp_instruction);
|
||||||
reply.content.push_back(tmpInstruction);
|
reply.content.push_back(temp_instruction);
|
||||||
roundAbout.leave_at_exit = 0;
|
round_about.leave_at_exit = 0;
|
||||||
} else {
|
} else {
|
||||||
intToString(current_instruction, tmpInstruction);
|
intToString(current_instruction, temp_instruction);
|
||||||
reply.content.push_back(tmpInstruction);
|
reply.content.push_back(temp_instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.content.push_back("\",\"");
|
reply.content.push_back("\",\"");
|
||||||
reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id));
|
reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id));
|
||||||
reply.content.push_back("\",");
|
reply.content.push_back("\",");
|
||||||
intToString(segment.length, tmpDist);
|
intToString(segment.length, temp_dist);
|
||||||
reply.content.push_back(tmpDist);
|
reply.content.push_back(temp_dist);
|
||||||
reply.content.push_back(",");
|
reply.content.push_back(",");
|
||||||
intToString(prefixSumOfNecessarySegments, tmpLength);
|
intToString(necessary_segments_running_index, temp_length);
|
||||||
reply.content.push_back(tmpLength);
|
reply.content.push_back(temp_length);
|
||||||
reply.content.push_back(",");
|
reply.content.push_back(",");
|
||||||
intToString(segment.duration/10, tmpDuration);
|
intToString(round(segment.duration/10.), temp_duration);
|
||||||
reply.content.push_back(tmpDuration);
|
reply.content.push_back(temp_duration);
|
||||||
reply.content.push_back(",\"");
|
reply.content.push_back(",\"");
|
||||||
intToString(segment.length, tmpLength);
|
intToString(segment.length, temp_length);
|
||||||
reply.content.push_back(tmpLength);
|
reply.content.push_back(temp_length);
|
||||||
reply.content.push_back("m\",\"");
|
reply.content.push_back("m\",\"");
|
||||||
double bearing_value = round(segment.bearing/10.);
|
double bearing_value = round(segment.bearing/10.);
|
||||||
reply.content.push_back(Azimuth::Get(bearing_value));
|
reply.content.push_back(Azimuth::Get(bearing_value));
|
||||||
reply.content.push_back("\",");
|
reply.content.push_back("\",");
|
||||||
intToString(bearing_value, tmpBearing);
|
intToString(bearing_value, temp_bearing);
|
||||||
reply.content.push_back(tmpBearing);
|
reply.content.push_back(temp_bearing);
|
||||||
reply.content.push_back("]");
|
reply.content.push_back("]");
|
||||||
|
|
||||||
route_segments_list.push_back(
|
route_segments_list.push_back(
|
||||||
@@ -479,22 +511,22 @@ public:
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if(TurnInstructions.StayOnRoundAbout == current_instruction) {
|
} else if(TurnInstructionsClass::StayOnRoundAbout == current_instruction) {
|
||||||
++roundAbout.leave_at_exit;
|
++round_about.leave_at_exit;
|
||||||
}
|
}
|
||||||
if(segment.necessary)
|
if(segment.necessary)
|
||||||
++prefixSumOfNecessarySegments;
|
++necessary_segments_running_index;
|
||||||
}
|
}
|
||||||
if(INT_MAX != route_length) {
|
if(INT_MAX != route_length) {
|
||||||
reply.content.push_back(",[\"");
|
reply.content.push_back(",[\"");
|
||||||
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
|
intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction);
|
||||||
reply.content.push_back(tmpInstruction);
|
reply.content.push_back(temp_instruction);
|
||||||
reply.content.push_back("\",\"");
|
reply.content.push_back("\",\"");
|
||||||
reply.content.push_back("\",");
|
reply.content.push_back("\",");
|
||||||
reply.content.push_back("0");
|
reply.content.push_back("0");
|
||||||
reply.content.push_back(",");
|
reply.content.push_back(",");
|
||||||
intToString(prefixSumOfNecessarySegments-1, tmpLength);
|
intToString(necessary_segments_running_index-1, temp_length);
|
||||||
reply.content.push_back(tmpLength);
|
reply.content.push_back(temp_length);
|
||||||
reply.content.push_back(",");
|
reply.content.push_back(",");
|
||||||
reply.content.push_back("0");
|
reply.content.push_back("0");
|
||||||
reply.content.push_back(",\"");
|
reply.content.push_back(",\"");
|
||||||
|
|||||||
@@ -362,7 +362,6 @@ void ExtractionContainers::PrepareData(
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw OSRMException("edge has broken direction");
|
throw OSRMException("edge has broken direction");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
file_out_stream.write(
|
file_out_stream.write(
|
||||||
(char*)&integer_weight, sizeof(int)
|
(char*)&integer_weight, sizeof(int)
|
||||||
@@ -373,23 +372,27 @@ void ExtractionContainers::PrepareData(
|
|||||||
sizeof(short)
|
sizeof(short)
|
||||||
);
|
);
|
||||||
file_out_stream.write(
|
file_out_stream.write(
|
||||||
(char*)&edge_iterator->nameID,
|
(char *) &edge_iterator->nameID,
|
||||||
sizeof(unsigned)
|
sizeof(unsigned)
|
||||||
);
|
);
|
||||||
file_out_stream.write(
|
file_out_stream.write(
|
||||||
(char*)&edge_iterator->isRoundabout,
|
(char *) &edge_iterator->isRoundabout,
|
||||||
sizeof(bool)
|
sizeof(bool)
|
||||||
);
|
);
|
||||||
file_out_stream.write(
|
file_out_stream.write(
|
||||||
(char*)&edge_iterator->ignoreInGrid,
|
(char *) &edge_iterator->ignoreInGrid,
|
||||||
sizeof(bool)
|
sizeof(bool)
|
||||||
);
|
);
|
||||||
file_out_stream.write(
|
file_out_stream.write(
|
||||||
(char*)&edge_iterator->isAccessRestricted,
|
(char *) &edge_iterator->isAccessRestricted,
|
||||||
sizeof(bool)
|
sizeof(bool)
|
||||||
);
|
);
|
||||||
file_out_stream.write(
|
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)
|
sizeof(bool)
|
||||||
);
|
);
|
||||||
++number_of_used_edges;
|
++number_of_used_edges;
|
||||||
|
|||||||
@@ -75,13 +75,13 @@ inline unsigned parseDuration(const std::string &s) {
|
|||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
|
// inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
|
||||||
boost::algorithm::to_lower(input);
|
// boost::algorithm::to_lower(input);
|
||||||
int n = stringToInt(input);
|
// int n = stringToInt(input);
|
||||||
if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
|
// if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
|
||||||
n = (n*1609)/1000;
|
// n = (n*1609)/1000;
|
||||||
}
|
// }
|
||||||
return n;
|
// return n;
|
||||||
}
|
// }
|
||||||
|
|
||||||
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
|
#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 "ExtractorCallbacks.h"
|
||||||
|
#include "ExtractionContainers.h"
|
||||||
|
#include "ExtractionWay.h"
|
||||||
|
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.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 <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
ExtractorCallbacks::ExtractorCallbacks()
|
ExtractorCallbacks::ExtractorCallbacks()
|
||||||
:
|
:
|
||||||
stringMap(NULL),
|
string_map(NULL),
|
||||||
externalMemory(NULL)
|
externalMemory(NULL)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
ExtractorCallbacks::ExtractorCallbacks(
|
ExtractorCallbacks::ExtractorCallbacks(
|
||||||
ExtractionContainers * ext,
|
ExtractionContainers * ext,
|
||||||
StringMap * strMap
|
boost::unordered_map<std::string, NodeID> * string_map
|
||||||
) :
|
) :
|
||||||
stringMap(strMap),
|
string_map(string_map),
|
||||||
externalMemory(ext)
|
externalMemory(ext)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -94,11 +88,11 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Get the unique identifier for the street name
|
//Get the unique identifier for the street name
|
||||||
const StringMap::const_iterator & string_map_iterator = stringMap->find(parsed_way.name);
|
const boost::unordered_map<std::string, NodeID>::const_iterator & string_map_iterator = string_map->find(parsed_way.name);
|
||||||
if(stringMap->end() == string_map_iterator) {
|
if(string_map->end() == string_map_iterator) {
|
||||||
parsed_way.nameID = externalMemory->name_list.size();
|
parsed_way.nameID = externalMemory->name_list.size();
|
||||||
externalMemory->name_list.push_back(parsed_way.name);
|
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 {
|
} else {
|
||||||
parsed_way.nameID = string_map_iterator->second;
|
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) {
|
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||||
externalMemory->all_edges_list.push_back(
|
externalMemory->all_edges_list.push_back(
|
||||||
InternalExtractorEdge(parsed_way.path[n],
|
InternalExtractorEdge(
|
||||||
parsed_way.path[n+1],
|
parsed_way.path[n],
|
||||||
parsed_way.type,
|
parsed_way.path[n+1],
|
||||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
parsed_way.type,
|
||||||
parsed_way.speed,
|
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||||
parsed_way.nameID,
|
parsed_way.speed,
|
||||||
parsed_way.roundabout,
|
parsed_way.nameID,
|
||||||
parsed_way.ignoreInGrid,
|
parsed_way.roundabout,
|
||||||
(0 < parsed_way.duration),
|
parsed_way.ignoreInGrid,
|
||||||
parsed_way.isAccessRestricted
|
(0 < parsed_way.duration),
|
||||||
|
parsed_way.isAccessRestricted,
|
||||||
|
false,
|
||||||
|
split_bidirectional_edge
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
externalMemory->used_node_id_list.push_back(parsed_way.path[n]);
|
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() );
|
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) {
|
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||||
externalMemory->all_edges_list.push_back(
|
externalMemory->all_edges_list.push_back(
|
||||||
InternalExtractorEdge(parsed_way.path[n],
|
InternalExtractorEdge(
|
||||||
parsed_way.path[n+1],
|
parsed_way.path[n],
|
||||||
parsed_way.type,
|
parsed_way.path[n+1],
|
||||||
ExtractionWay::oneway,
|
parsed_way.type,
|
||||||
parsed_way.backward_speed,
|
ExtractionWay::oneway,
|
||||||
parsed_way.nameID,
|
parsed_way.backward_speed,
|
||||||
parsed_way.roundabout,
|
parsed_way.nameID,
|
||||||
parsed_way.ignoreInGrid,
|
parsed_way.roundabout,
|
||||||
(0 < parsed_way.duration),
|
parsed_way.ignoreInGrid,
|
||||||
parsed_way.isAccessRestricted,
|
(0 < parsed_way.duration),
|
||||||
(ExtractionWay::oneway == parsed_way.direction)
|
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_
|
#ifndef EXTRACTORCALLBACKS_H_
|
||||||
#define EXTRACTORCALLBACKS_H_
|
#define EXTRACTORCALLBACKS_H_
|
||||||
|
|
||||||
#include "ExtractorStructs.h"
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
struct ExternalMemoryNode;
|
||||||
class ExtractionContainers;
|
class ExtractionContainers;
|
||||||
struct ExtractionWay;
|
struct ExtractionWay;
|
||||||
struct InputRestrictionContainer;
|
struct InputRestrictionContainer;
|
||||||
|
|
||||||
typedef boost::unordered_map<std::string, NodeID> StringMap;
|
|
||||||
|
|
||||||
class ExtractorCallbacks{
|
class ExtractorCallbacks{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
StringMap * stringMap;
|
boost::unordered_map<std::string, NodeID> * string_map;
|
||||||
ExtractionContainers * externalMemory;
|
ExtractionContainers * externalMemory;
|
||||||
|
|
||||||
ExtractorCallbacks();
|
ExtractorCallbacks();
|
||||||
public:
|
public:
|
||||||
explicit ExtractorCallbacks(
|
explicit ExtractorCallbacks(
|
||||||
ExtractionContainers * ext,
|
ExtractionContainers * ext,
|
||||||
StringMap * strMap
|
boost::unordered_map<std::string, NodeID> * string_map
|
||||||
);
|
);
|
||||||
|
|
||||||
~ExtractorCallbacks();
|
~ExtractorCallbacks();
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef INTERNAL_EXTRACTOR_EDGE_H
|
#ifndef INTERNAL_EXTRACTOR_EDGE_H
|
||||||
#define INTERNAL_EXTRACTOR_EDGE_H
|
#define INTERNAL_EXTRACTOR_EDGE_H
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
@@ -47,70 +47,10 @@ struct InternalExtractorEdge {
|
|||||||
ignoreInGrid(false),
|
ignoreInGrid(false),
|
||||||
isDurationSet(false),
|
isDurationSet(false),
|
||||||
isAccessRestricted(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(
|
explicit InternalExtractorEdge(
|
||||||
NodeID start,
|
NodeID start,
|
||||||
@@ -123,7 +63,8 @@ struct InternalExtractorEdge {
|
|||||||
bool ignoreInGrid,
|
bool ignoreInGrid,
|
||||||
bool isDurationSet,
|
bool isDurationSet,
|
||||||
bool isAccressRestricted,
|
bool isAccressRestricted,
|
||||||
bool isContraFlow
|
bool isContraFlow,
|
||||||
|
bool is_split
|
||||||
) :
|
) :
|
||||||
start(start),
|
start(start),
|
||||||
target(target),
|
target(target),
|
||||||
@@ -135,19 +76,43 @@ struct InternalExtractorEdge {
|
|||||||
ignoreInGrid(ignoreInGrid),
|
ignoreInGrid(ignoreInGrid),
|
||||||
isDurationSet(isDurationSet),
|
isDurationSet(isDurationSet),
|
||||||
isAccessRestricted(isAccressRestricted),
|
isAccessRestricted(isAccressRestricted),
|
||||||
isContraFlow(isContraFlow)
|
isContraFlow(isContraFlow),
|
||||||
|
is_split(is_split)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(0 <= type);
|
BOOST_ASSERT(0 <= type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// necessary static util functions for stxxl's sorting
|
// necessary static util functions for stxxl's sorting
|
||||||
static InternalExtractorEdge min_value() {
|
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() {
|
static InternalExtractorEdge max_value() {
|
||||||
return InternalExtractorEdge(
|
return InternalExtractorEdge(
|
||||||
std::numeric_limits<unsigned>::max(),
|
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 isDurationSet;
|
||||||
bool isAccessRestricted;
|
bool isAccessRestricted;
|
||||||
bool isContraFlow;
|
bool isContraFlow;
|
||||||
|
bool is_split;
|
||||||
|
|
||||||
FixedPointCoordinate startCoord;
|
FixedPointCoordinate startCoord;
|
||||||
FixedPointCoordinate targetCoord;
|
FixedPointCoordinate targetCoord;
|
||||||
|
|||||||
+24
-22
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "ScriptingEnvironment.h"
|
#include "ScriptingEnvironment.h"
|
||||||
|
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../Util/MachineInfo.h"
|
#include "../Util/MachineInfo.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
#include "../Util/OpenMPWrapper.h"
|
||||||
@@ -214,25 +215,26 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
|||||||
denseTagIndex += 2;
|
denseTagIndex += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma omp parallel
|
||||||
|
{
|
||||||
|
const int thread_num = omp_get_thread_num();
|
||||||
#pragma omp parallel for schedule ( guided )
|
#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];
|
ImportNode & import_node = extracted_nodes_vector[i];
|
||||||
ParseNodeInLua(
|
ParseNodeInLua(import_node, scripting_environment.getLuaStateForThreadID(thread_num));
|
||||||
import_node,
|
|
||||||
scripting_environment.getLuaStateForThreadID(omp_get_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);
|
extractor_callbacks->nodeFunction(import_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::parseNode(_ThreadData * ) {
|
inline void PBFParser::parseNode(_ThreadData * )
|
||||||
throw OSRMException(
|
{
|
||||||
"Parsing of simple nodes not supported. PBF should use dense nodes"
|
throw OSRMException("Parsing of simple nodes not supported. PBF should use dense nodes");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||||
@@ -351,24 +353,24 @@ inline void PBFParser::parseWay(_ThreadData * threadData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma omp parallel for schedule ( guided )
|
#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];
|
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) {
|
BOOST_FOREACH(ExtractionWay & extraction_way, parsed_way_vector)
|
||||||
if (2 > extraction_way.path.size())
|
{
|
||||||
|
if (2 <= extraction_way.path.size())
|
||||||
{
|
{
|
||||||
continue;
|
extractor_callbacks->wayFunction(extraction_way);
|
||||||
}
|
}
|
||||||
extractor_callbacks->wayFunction(extraction_way);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,13 +76,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
inline void ReadData();
|
inline void ReadData();
|
||||||
inline void ParseData();
|
inline void ParseData();
|
||||||
inline void parseDenseNode (_ThreadData * threadData);
|
inline void parseDenseNode (_ThreadData * threadData);
|
||||||
inline void parseNode (_ThreadData * threadData);
|
inline void parseNode (_ThreadData * threadData);
|
||||||
inline void parseRelation (_ThreadData * threadData);
|
inline void parseRelation (_ThreadData * threadData);
|
||||||
inline void parseWay (_ThreadData * threadData);
|
inline void parseWay (_ThreadData * threadData);
|
||||||
|
|
||||||
inline void loadGroup (_ThreadData * threadData);
|
inline void loadGroup (_ThreadData * threadData);
|
||||||
inline void loadBlock (_ThreadData * threadData);
|
inline void loadBlock (_ThreadData * threadData);
|
||||||
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
|
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
|
||||||
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData);
|
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData);
|
||||||
inline bool unpackLZMA (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
|
// Add our function to the state's global scope
|
||||||
luabind::module(myLuaState) [
|
luabind::module(myLuaState) [
|
||||||
luabind::def("print", LUA_print<std::string>),
|
luabind::def("print", LUA_print<std::string>),
|
||||||
luabind::def("parseMaxspeed", parseMaxspeed),
|
|
||||||
luabind::def("durationIsValid", durationIsValid),
|
luabind::def("durationIsValid", durationIsValid),
|
||||||
luabind::def("parseDuration", parseDuration)
|
luabind::def("parseDuration", parseDuration)
|
||||||
];
|
];
|
||||||
@@ -106,9 +105,8 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
|||||||
|
|
||||||
// fails on c++11/OS X 10.9
|
// fails on c++11/OS X 10.9
|
||||||
luabind::module(myLuaState) [
|
luabind::module(myLuaState) [
|
||||||
luabind::class_<std::vector<std::string> >("vector")
|
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)
|
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back))
|
||||||
)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ struct lua_State;
|
|||||||
class ScriptingEnvironment {
|
class ScriptingEnvironment {
|
||||||
public:
|
public:
|
||||||
ScriptingEnvironment();
|
ScriptingEnvironment();
|
||||||
ScriptingEnvironment(const char * fileName);
|
explicit ScriptingEnvironment(const char * fileName);
|
||||||
virtual ~ScriptingEnvironment();
|
virtual ~ScriptingEnvironment();
|
||||||
|
|
||||||
lua_State * getLuaStateForThreadID(const int);
|
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 "XMLParser.h"
|
||||||
|
|
||||||
#include "ExtractionWay.h"
|
#include "ExtractionWay.h"
|
||||||
|
#include "ExtractorCallbacks.h"
|
||||||
|
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../DataStructures/InputReaderFactory.h"
|
#include "../DataStructures/InputReaderFactory.h"
|
||||||
@@ -40,249 +42,307 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
|
|
||||||
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
|
XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se)
|
||||||
inputReader = inputReaderFactory(filename);
|
: BaseParser(ec, se)
|
||||||
|
{
|
||||||
|
inputReader = inputReaderFactory(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XMLParser::ReadHeader() {
|
bool XMLParser::ReadHeader() { return (xmlTextReaderRead(inputReader) == 1); }
|
||||||
return (xmlTextReaderRead( inputReader ) == 1);
|
bool XMLParser::Parse()
|
||||||
}
|
{
|
||||||
bool XMLParser::Parse() {
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
{
|
||||||
const int type = xmlTextReaderNodeType( inputReader );
|
const int type = xmlTextReaderNodeType(inputReader);
|
||||||
|
|
||||||
//1 is Element
|
// 1 is Element
|
||||||
if ( type != 1 ) {
|
if (type != 1)
|
||||||
continue;
|
{
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
xmlChar* currentName = xmlTextReaderName( inputReader );
|
xmlChar *currentName = xmlTextReaderName(inputReader);
|
||||||
if ( currentName == NULL ) {
|
if (currentName == NULL)
|
||||||
continue;
|
{
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
|
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
|
||||||
ImportNode n = _ReadXMLNode();
|
{
|
||||||
ParseNodeInLua( n, lua_state );
|
ImportNode n = ReadXMLNode();
|
||||||
extractor_callbacks->nodeFunction(n);
|
ParseNodeInLua(n, lua_state);
|
||||||
// if(!extractor_callbacks->nodeFunction(n))
|
extractor_callbacks->nodeFunction(n);
|
||||||
// std::cerr << "[XMLParser] dense node not parsed" << std::endl;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
|
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
|
||||||
ExtractionWay way = _ReadXMLWay( );
|
{
|
||||||
ParseWayInLua( way, lua_state );
|
ExtractionWay way = ReadXMLWay();
|
||||||
extractor_callbacks->wayFunction(way);
|
ParseWayInLua(way, lua_state);
|
||||||
// if(!extractor_callbacks->wayFunction(way))
|
extractor_callbacks->wayFunction(way);
|
||||||
// std::cerr << "[PBFParser] way not parsed" << std::endl;
|
}
|
||||||
}
|
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
|
||||||
if( use_turn_restrictions ) {
|
{
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
InputRestrictionContainer r = ReadXMLRestriction();
|
||||||
InputRestrictionContainer r = _ReadXMLRestriction();
|
if ((UINT_MAX != r.fromWay) && !extractor_callbacks->restrictionFunction(r))
|
||||||
if(r.fromWay != UINT_MAX) {
|
{
|
||||||
if(!extractor_callbacks->restrictionFunction(r)) {
|
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
}
|
||||||
}
|
}
|
||||||
}
|
xmlFree(currentName);
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
xmlFree( currentName );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
||||||
|
{
|
||||||
InputRestrictionContainer restriction;
|
InputRestrictionContainer restriction;
|
||||||
std::string except_tag_string;
|
std::string except_tag_string;
|
||||||
|
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
||||||
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
{
|
||||||
const int childType = xmlTextReaderNodeType( inputReader );
|
const int depth = xmlTextReaderDepth(inputReader);
|
||||||
if ( childType != 1 && childType != 15 ) {
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
continue;
|
{
|
||||||
}
|
const int childType = xmlTextReaderNodeType(inputReader);
|
||||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
if (childType != 1 && childType != 15)
|
||||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
{
|
||||||
if ( childName == NULL ) {
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
const int childDepth = xmlTextReaderDepth(inputReader);
|
||||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
|
xmlChar *childName = xmlTextReaderName(inputReader);
|
||||||
xmlFree( childName );
|
if (childName == NULL)
|
||||||
break;
|
{
|
||||||
}
|
continue;
|
||||||
if ( childType != 1 ) {
|
}
|
||||||
xmlFree( childName );
|
if (depth == childDepth && childType == 15 &&
|
||||||
continue;
|
xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
|
||||||
}
|
{
|
||||||
|
xmlFree(childName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (childType != 1)
|
||||||
|
{
|
||||||
|
xmlFree(childName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
||||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
{
|
||||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
if ( k != NULL && value != NULL ) {
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
|
if (k != NULL && value != NULL)
|
||||||
if(0 == std::string((const char *) value).find("only_")) {
|
{
|
||||||
restriction.restriction.flags.isOnly = true;
|
if (xmlStrEqual(k, (const xmlChar *)"restriction") &&
|
||||||
}
|
(0 == std::string((const char *)value).find("only_")))
|
||||||
}
|
{
|
||||||
if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
|
restriction.restriction.flags.isOnly = true;
|
||||||
except_tag_string = (const char*) value;
|
}
|
||||||
}
|
if (xmlStrEqual(k, (const xmlChar *)"except"))
|
||||||
}
|
{
|
||||||
|
except_tag_string = (const char *)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( k != NULL ) {
|
if (k != NULL)
|
||||||
xmlFree( k );
|
{
|
||||||
}
|
xmlFree(k);
|
||||||
if ( value != NULL ) {
|
}
|
||||||
xmlFree( value );
|
if (value != NULL)
|
||||||
}
|
{
|
||||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
|
xmlFree(value);
|
||||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
}
|
||||||
if ( ref != NULL ) {
|
}
|
||||||
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
|
else if (xmlStrEqual(childName, (const xmlChar *)"member") == 1)
|
||||||
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
|
{
|
||||||
|
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")) {
|
if (xmlStrEqual(role, (const xmlChar *)"to") &&
|
||||||
restriction.toWay = stringToUint((const char*) ref);
|
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||||
}
|
{
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
restriction.toWay = stringToUint((const char *)ref);
|
||||||
restriction.fromWay = stringToUint((const char*) ref);
|
}
|
||||||
}
|
if (xmlStrEqual(role, (const xmlChar *)"from") &&
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
|
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||||
restriction.restriction.viaNode = stringToUint((const char*) ref);
|
{
|
||||||
}
|
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) {
|
if (NULL != type)
|
||||||
xmlFree( type );
|
{
|
||||||
}
|
xmlFree(type);
|
||||||
if(NULL != role) {
|
}
|
||||||
xmlFree( role );
|
if (NULL != role)
|
||||||
}
|
{
|
||||||
if(NULL != ref) {
|
xmlFree(role);
|
||||||
xmlFree( ref );
|
}
|
||||||
}
|
if (NULL != ref)
|
||||||
}
|
{
|
||||||
}
|
xmlFree(ref);
|
||||||
xmlFree( childName );
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
xmlFree(childName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( ShouldIgnoreRestriction(except_tag_string) ) {
|
if (ShouldIgnoreRestriction(except_tag_string))
|
||||||
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
|
{
|
||||||
}
|
restriction.fromWay = UINT_MAX; // workaround to ignore the restriction
|
||||||
return restriction;
|
}
|
||||||
|
return restriction;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractionWay XMLParser::_ReadXMLWay() {
|
ExtractionWay XMLParser::ReadXMLWay()
|
||||||
ExtractionWay way;
|
{
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
ExtractionWay way;
|
||||||
const int depth = xmlTextReaderDepth( inputReader );
|
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
||||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
{
|
||||||
const int childType = xmlTextReaderNodeType( inputReader );
|
const int depth = xmlTextReaderDepth(inputReader);
|
||||||
if ( childType != 1 && childType != 15 ) {
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
continue;
|
{
|
||||||
}
|
const int childType = xmlTextReaderNodeType(inputReader);
|
||||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
if (childType != 1 && childType != 15)
|
||||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
{
|
||||||
if ( childName == NULL ) {
|
continue;
|
||||||
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 ) {
|
if (depth == childDepth && childType == 15 &&
|
||||||
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
xmlStrEqual(childName, (const xmlChar *)"way") == 1)
|
||||||
way.id = stringToUint((char*)id);
|
{
|
||||||
xmlFree(id);
|
xmlChar *id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||||
xmlFree( childName );
|
way.id = stringToUint((char *)id);
|
||||||
break;
|
xmlFree(id);
|
||||||
}
|
xmlFree(childName);
|
||||||
if ( childType != 1 ) {
|
break;
|
||||||
xmlFree( childName );
|
}
|
||||||
continue;
|
if (childType != 1)
|
||||||
}
|
{
|
||||||
|
xmlFree(childName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
||||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
{
|
||||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
// cout << "->k=" << k << ", v=" << value << endl;
|
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 && value != NULL)
|
||||||
}
|
{
|
||||||
if ( k != NULL ) {
|
way.keyVals.Add(std::string((char *)k), std::string((char *)value));
|
||||||
xmlFree( k );
|
}
|
||||||
}
|
if (k != NULL)
|
||||||
if ( value != NULL ) {
|
{
|
||||||
xmlFree( value );
|
xmlFree(k);
|
||||||
}
|
}
|
||||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
|
if (value != NULL)
|
||||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
{
|
||||||
if ( ref != NULL ) {
|
xmlFree(value);
|
||||||
way.path.push_back( stringToUint(( const char* ) ref ) );
|
}
|
||||||
xmlFree( ref );
|
}
|
||||||
}
|
else if (xmlStrEqual(childName, (const xmlChar *)"nd") == 1)
|
||||||
}
|
{
|
||||||
xmlFree( childName );
|
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||||
}
|
if (ref != NULL)
|
||||||
}
|
{
|
||||||
return way;
|
way.path.push_back(stringToUint((const char *)ref));
|
||||||
|
xmlFree(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFree(childName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return way;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportNode XMLParser::_ReadXMLNode() {
|
ImportNode XMLParser::ReadXMLNode()
|
||||||
ImportNode node;
|
{
|
||||||
|
ImportNode node;
|
||||||
|
|
||||||
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
|
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
|
||||||
if ( attribute != NULL ) {
|
if (attribute != NULL)
|
||||||
node.lat = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ) );
|
{
|
||||||
xmlFree( attribute );
|
node.lat = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
||||||
}
|
xmlFree(attribute);
|
||||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
|
}
|
||||||
if ( attribute != NULL ) {
|
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
|
||||||
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ));
|
if (attribute != NULL)
|
||||||
xmlFree( attribute );
|
{
|
||||||
}
|
node.lon = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
||||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
xmlFree(attribute);
|
||||||
if ( attribute != NULL ) {
|
}
|
||||||
node.id = stringToUint(( const char* ) attribute );
|
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||||
xmlFree( attribute );
|
if (attribute != NULL)
|
||||||
}
|
{
|
||||||
|
node.id = stringToUint((const char *)attribute);
|
||||||
|
xmlFree(attribute);
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
||||||
const int depth = xmlTextReaderDepth( inputReader );
|
{
|
||||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
const int depth = xmlTextReaderDepth(inputReader);
|
||||||
const int childType = xmlTextReaderNodeType( inputReader );
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
// 1 = Element, 15 = EndElement
|
{
|
||||||
if ( childType != 1 && childType != 15 ) {
|
const int childType = xmlTextReaderNodeType(inputReader);
|
||||||
continue;
|
// 1 = Element, 15 = EndElement
|
||||||
}
|
if (childType != 1 && childType != 15)
|
||||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
{
|
||||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
continue;
|
||||||
if ( childName == NULL ) {
|
}
|
||||||
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 ) {
|
if (depth == childDepth && childType == 15 &&
|
||||||
xmlFree( childName );
|
xmlStrEqual(childName, (const xmlChar *)"node") == 1)
|
||||||
break;
|
{
|
||||||
}
|
xmlFree(childName);
|
||||||
if ( childType != 1 ) {
|
break;
|
||||||
xmlFree( childName );
|
}
|
||||||
continue;
|
if (childType != 1)
|
||||||
}
|
{
|
||||||
|
xmlFree(childName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
||||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
{
|
||||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
if ( k != NULL && value != NULL ) {
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
|
if (k != NULL && value != NULL)
|
||||||
}
|
{
|
||||||
if ( k != NULL ) {
|
node.keyVals.emplace(std::string((char *)(k)),
|
||||||
xmlFree( k );
|
std::string((char *)(value)));
|
||||||
}
|
}
|
||||||
if ( value != NULL ) {
|
if (k != NULL)
|
||||||
xmlFree( value );
|
{
|
||||||
}
|
xmlFree(k);
|
||||||
}
|
}
|
||||||
|
if (value != NULL)
|
||||||
|
{
|
||||||
|
xmlFree(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xmlFree( childName );
|
xmlFree(childName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-12
@@ -33,21 +33,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
|
||||||
|
class XMLParser : public BaseParser
|
||||||
class XMLParser : public BaseParser {
|
{
|
||||||
public:
|
public:
|
||||||
XMLParser(
|
XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se);
|
||||||
const char* filename,
|
|
||||||
ExtractorCallbacks* ec,
|
|
||||||
ScriptingEnvironment& se
|
|
||||||
);
|
|
||||||
bool ReadHeader();
|
bool ReadHeader();
|
||||||
bool Parse();
|
bool Parse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
InputRestrictionContainer _ReadXMLRestriction();
|
InputRestrictionContainer ReadXMLRestriction();
|
||||||
ExtractionWay _ReadXMLWay();
|
ExtractionWay ReadXMLWay();
|
||||||
ImportNode _ReadXMLNode();
|
ImportNode ReadXMLNode();
|
||||||
xmlTextReaderPtr inputReader;
|
xmlTextReaderPtr inputReader;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef FIXED_POINT_COORDINATE_H_
|
#ifndef FIXED_POINT_COORDINATE_H_
|
||||||
#define FIXED_POINT_COORDINATE_H_
|
#define FIXED_POINT_COORDINATE_H_
|
||||||
|
|
||||||
#include <iostream>
|
#include <iosfwd> //for std::ostream
|
||||||
|
|
||||||
static const double COORDINATE_PRECISION = 1000000.;
|
static const double COORDINATE_PRECISION = 1000000.;
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ struct FixedPointCoordinate {
|
|||||||
int lon;
|
int lon;
|
||||||
|
|
||||||
FixedPointCoordinate();
|
FixedPointCoordinate();
|
||||||
explicit FixedPointCoordinate (int lat, int lon);
|
explicit FixedPointCoordinate( int lat, int lon);
|
||||||
void Reset();
|
void Reset();
|
||||||
bool isSet() const;
|
bool isSet() const;
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
@@ -74,11 +74,13 @@ struct FixedPointCoordinate {
|
|||||||
const FixedPointCoordinate & coord,
|
const FixedPointCoordinate & coord,
|
||||||
std::string & output
|
std::string & output
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void Output(std::ostream & out) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){
|
inline std::ostream& operator<<(std::ostream& o, FixedPointCoordinate const & c){
|
||||||
out << "(" << c.lat << "," << c.lon << ")";
|
c.Output(o);
|
||||||
return out;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
const char okHTML[] = "";
|
const char okHTML[] = "";
|
||||||
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
|
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
|
||||||
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
|
const char internalServerErrorHTML[] = "{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
|
||||||
const char seperators[] = { ':', ' ' };
|
const char seperators[] = { ':', ' ' };
|
||||||
const char crlf[] = { '\r', '\n' };
|
const char crlf[] = { '\r', '\n' };
|
||||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
|
|
||||||
Reply();
|
Reply();
|
||||||
private:
|
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);
|
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
|
#ifndef OSRM_H
|
||||||
#define OSRM_H
|
#define OSRM_H
|
||||||
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
|
|
||||||
#include <osrm/Reply.h>
|
#include <osrm/Reply.h>
|
||||||
#include <osrm/RouteParameters.h>
|
#include <osrm/RouteParameters.h>
|
||||||
#include <osrm/ServerPaths.h>
|
#include <osrm/ServerPaths.h>
|
||||||
@@ -40,7 +38,7 @@ class OSRM {
|
|||||||
private:
|
private:
|
||||||
OSRM_impl * OSRM_pimpl_;
|
OSRM_impl * OSRM_pimpl_;
|
||||||
public:
|
public:
|
||||||
OSRM(
|
explicit OSRM(
|
||||||
const ServerPaths & paths,
|
const ServerPaths & paths,
|
||||||
const bool use_shared_memory = false
|
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_impl.h"
|
||||||
|
#include "OSRM.h"
|
||||||
|
|
||||||
#include "../Plugins/HelloWorldPlugin.h"
|
#include "../Plugins/HelloWorldPlugin.h"
|
||||||
#include "../Plugins/LocatePlugin.h"
|
#include "../Plugins/LocatePlugin.h"
|
||||||
|
|||||||
@@ -28,10 +28,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef BASEPLUGIN_H_
|
#ifndef BASEPLUGIN_H_
|
||||||
#define BASEPLUGIN_H_
|
#define BASEPLUGIN_H_
|
||||||
|
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
#include <osrm/Reply.h>
|
#include <osrm/Reply.h>
|
||||||
#include <osrm/RouteParameters.h>
|
#include <osrm/RouteParameters.h>
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
template<class DataFacadeT>
|
template<class DataFacadeT>
|
||||||
class LocatePlugin : public BasePlugin {
|
class LocatePlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
LocatePlugin(DataFacadeT * facade)
|
explicit LocatePlugin(DataFacadeT * facade)
|
||||||
:
|
:
|
||||||
descriptor_string("locate"),
|
descriptor_string("locate"),
|
||||||
facade(facade)
|
facade(facade)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
template<class DataFacadeT>
|
template<class DataFacadeT>
|
||||||
class NearestPlugin : public BasePlugin {
|
class NearestPlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
NearestPlugin(DataFacadeT * facade )
|
explicit NearestPlugin(DataFacadeT * facade )
|
||||||
:
|
:
|
||||||
facade(facade),
|
facade(facade),
|
||||||
descriptor_string("nearest")
|
descriptor_string("nearest")
|
||||||
@@ -50,10 +50,9 @@ public:
|
|||||||
descriptorTable.emplace("json", 1);
|
descriptorTable.emplace("json", 1);
|
||||||
}
|
}
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
|
|
||||||
void HandleRequest(
|
void HandleRequest(
|
||||||
const RouteParameters & routeParameters,
|
const RouteParameters & routeParameters,
|
||||||
http::Reply& reply
|
http::Reply & reply
|
||||||
) {
|
) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if(!routeParameters.coordinates.size()) {
|
if(!routeParameters.coordinates.size()) {
|
||||||
@@ -82,13 +81,13 @@ public:
|
|||||||
|
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content.push_back("{\"status\":");
|
reply.content.push_back("{\"status\":");
|
||||||
if(UINT_MAX != result.edgeBasedNode) {
|
if(UINT_MAX != result.forward_node_id) {
|
||||||
reply.content.push_back("0,");
|
reply.content.push_back("0,");
|
||||||
} else {
|
} else {
|
||||||
reply.content.push_back("207,");
|
reply.content.push_back("207,");
|
||||||
}
|
}
|
||||||
reply.content.push_back("\"mapped_coordinate\":[");
|
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);
|
FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
|
||||||
reply.content.push_back(temp_string);
|
reply.content.push_back(temp_string);
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
|
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
|
||||||
@@ -96,8 +95,8 @@ public:
|
|||||||
reply.content.push_back(temp_string);
|
reply.content.push_back(temp_string);
|
||||||
}
|
}
|
||||||
reply.content.push_back("],\"name\":\"");
|
reply.content.push_back("],\"name\":\"");
|
||||||
if(UINT_MAX != result.edgeBasedNode) {
|
if(UINT_MAX != result.forward_node_id) {
|
||||||
facade->GetName(result.nodeBasedEdgeNameID, temp_string);
|
facade->GetName(result.name_id, temp_string);
|
||||||
reply.content.push_back(temp_string);
|
reply.content.push_back(temp_string);
|
||||||
}
|
}
|
||||||
reply.content.push_back("\"}");
|
reply.content.push_back("\"}");
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
template<class DataFacadeT>
|
template<class DataFacadeT>
|
||||||
class TimestampPlugin : public BasePlugin {
|
class TimestampPlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
TimestampPlugin(const DataFacadeT * facade)
|
explicit TimestampPlugin(const DataFacadeT * facade)
|
||||||
: facade(facade), descriptor_string("timestamp")
|
: facade(facade), descriptor_string("timestamp")
|
||||||
{ }
|
{ }
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
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/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -50,24 +52,21 @@ template<class DataFacadeT>
|
|||||||
class ViaRoutePlugin : public BasePlugin {
|
class ViaRoutePlugin : public BasePlugin {
|
||||||
private:
|
private:
|
||||||
boost::unordered_map<std::string, unsigned> descriptorTable;
|
boost::unordered_map<std::string, unsigned> descriptorTable;
|
||||||
SearchEngine<DataFacadeT> * search_engine_ptr;
|
boost::shared_ptr<SearchEngine<DataFacadeT> > search_engine_ptr;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ViaRoutePlugin(DataFacadeT * facade)
|
explicit ViaRoutePlugin(DataFacadeT * facade)
|
||||||
:
|
:
|
||||||
descriptor_string("viaroute"),
|
descriptor_string("viaroute"),
|
||||||
facade(facade)
|
facade(facade)
|
||||||
{
|
{
|
||||||
//TODO: set up an engine for each thread!!
|
search_engine_ptr = boost::make_shared<SearchEngine<DataFacadeT> >(facade);
|
||||||
search_engine_ptr = new SearchEngine<DataFacadeT>(facade);
|
|
||||||
|
|
||||||
descriptorTable.emplace("json", 0);
|
descriptorTable.emplace("json", 0);
|
||||||
descriptorTable.emplace("gpx" , 1);
|
descriptorTable.emplace("gpx" , 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ViaRoutePlugin() {
|
virtual ~ViaRoutePlugin() { }
|
||||||
delete search_engine_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
|
|
||||||
@@ -81,115 +80,106 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawRouteData rawRoute;
|
RawRouteData raw_route;
|
||||||
rawRoute.checkSum = facade->GetCheckSum();
|
raw_route.checkSum = facade->GetCheckSum();
|
||||||
const bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
const bool checksumOK = (routeParameters.checkSum == raw_route.checkSum);
|
||||||
std::vector<std::string> textCoord;
|
std::vector<std::string> textCoord;
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||||
if( !checkCoord(routeParameters.coordinates[i]) ) {
|
if( !checkCoord(routeParameters.coordinates[i]) ) {
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
raw_route.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
||||||
}
|
}
|
||||||
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
|
std::vector<PhantomNode> phantomNodeVector(raw_route.rawViaNodeCoordinates.size());
|
||||||
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
|
for(unsigned i = 0; i < raw_route.rawViaNodeCoordinates.size(); ++i) {
|
||||||
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[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]);
|
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
|
||||||
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
|
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
|
||||||
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
|
|
||||||
facade->FindPhantomNodeForCoordinate(
|
facade->FindPhantomNodeForCoordinate(
|
||||||
rawRoute.rawViaNodeCoordinates[i],
|
raw_route.rawViaNodeCoordinates[i],
|
||||||
phantomNodeVector[i],
|
phantomNodeVector[i],
|
||||||
routeParameters.zoomLevel
|
routeParameters.zoomLevel
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomNodes segmentPhantomNodes;
|
PhantomNodes current_phantom_node_pair;
|
||||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
for (unsigned i = 0; i < phantomNodeVector.size()-1; ++i)
|
||||||
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
|
{
|
||||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
current_phantom_node_pair.source_phantom = phantomNodeVector[i];
|
||||||
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
current_phantom_node_pair.target_phantom = phantomNodeVector[i+1];
|
||||||
|
raw_route.segmentEndCoordinates.push_back(current_phantom_node_pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(
|
if ((routeParameters.alternateRoute) && (1 == raw_route.segmentEndCoordinates.size()))
|
||||||
( routeParameters.alternateRoute ) &&
|
{
|
||||||
(1 == rawRoute.segmentEndCoordinates.size())
|
search_engine_ptr->alternative_path(raw_route.segmentEndCoordinates[0], raw_route);
|
||||||
) {
|
}
|
||||||
search_engine_ptr->alternative_path(
|
else
|
||||||
rawRoute.segmentEndCoordinates[0],
|
{
|
||||||
rawRoute
|
search_engine_ptr->shortest_path(raw_route.segmentEndCoordinates, raw_route);
|
||||||
);
|
|
||||||
} else {
|
|
||||||
search_engine_ptr->shortest_path(
|
|
||||||
rawRoute.segmentEndCoordinates,
|
|
||||||
rawRoute
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
if (INT_MAX == raw_route.lengthOfShortestPath)
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
{
|
||||||
"Error occurred, single path not found";
|
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
||||||
}
|
}
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
|
|
||||||
//TODO: Move to member as smart pointer
|
if (!routeParameters.jsonpParameter.empty())
|
||||||
BaseDescriptor<DataFacadeT> * desc;
|
{
|
||||||
if("" != routeParameters.jsonpParameter) {
|
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
reply.content.push_back("(");
|
reply.content.push_back("(");
|
||||||
}
|
}
|
||||||
|
|
||||||
DescriptorConfig descriptorConfig;
|
DescriptorConfig descriptor_config;
|
||||||
|
|
||||||
unsigned descriptorType = 0;
|
unsigned descriptor_type = 0;
|
||||||
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
|
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;
|
descriptor_config.zoom_level = routeParameters.zoomLevel;
|
||||||
descriptorConfig.instructions = routeParameters.printInstructions;
|
descriptor_config.instructions = routeParameters.printInstructions;
|
||||||
descriptorConfig.geometry = routeParameters.geometry;
|
descriptor_config.geometry = routeParameters.geometry;
|
||||||
descriptorConfig.encode_geometry = routeParameters.compression;
|
descriptor_config.encode_geometry = routeParameters.compression;
|
||||||
|
|
||||||
switch(descriptorType){
|
boost::shared_ptr<BaseDescriptor<DataFacadeT> > descriptor;
|
||||||
|
switch(descriptor_type){
|
||||||
case 0:
|
case 0:
|
||||||
desc = new JSONDescriptor<DataFacadeT>();
|
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
desc = new GPXDescriptor<DataFacadeT>();
|
descriptor = boost::make_shared<GPXDescriptor<DataFacadeT> >();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
desc = new JSONDescriptor<DataFacadeT>();
|
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomNodes phantomNodes;
|
PhantomNodes phantom_nodes;
|
||||||
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
phantom_nodes.source_phantom = raw_route.segmentEndCoordinates[0].source_phantom;
|
||||||
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
|
phantom_nodes.target_phantom = raw_route.segmentEndCoordinates[raw_route.segmentEndCoordinates.size()-1].target_phantom;
|
||||||
desc->SetConfig(descriptorConfig);
|
descriptor->SetConfig(descriptor_config);
|
||||||
|
|
||||||
desc->Run(rawRoute, phantomNodes, facade, reply);
|
descriptor->Run(raw_route, phantom_nodes, facade, reply);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
|
||||||
|
if (!routeParameters.jsonpParameter.empty())
|
||||||
|
{
|
||||||
reply.content.push_back(")\n");
|
reply.content.push_back(")\n");
|
||||||
}
|
}
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
reply.headers[0].name = "Content-Length";
|
reply.headers[0].name = "Content-Length";
|
||||||
std::string tmp;
|
|
||||||
unsigned content_length = 0;
|
unsigned content_length = 0;
|
||||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||||
content_length += snippet.length();
|
content_length += snippet.length();
|
||||||
}
|
}
|
||||||
intToString(content_length, tmp);
|
std::string tmp_string;
|
||||||
reply.headers[0].value = tmp;
|
intToString(content_length, tmp_string);
|
||||||
switch(descriptorType){
|
reply.headers[0].value = tmp_string;
|
||||||
|
switch(descriptor_type){
|
||||||
case 0:
|
case 0:
|
||||||
if( !routeParameters.jsonpParameter.empty() ){
|
if( !routeParameters.jsonpParameter.empty() ){
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
@@ -225,8 +215,6 @@ public:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete desc;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
private:
|
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/RawRouteData.h"
|
||||||
#include "../DataStructures/SearchEngineData.h"
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/ContainerUtils.h"
|
#include "../Util/ContainerUtils.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
||||||
@@ -54,7 +54,7 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
DataFacadeT * facade;
|
DataFacadeT * facade;
|
||||||
public:
|
public:
|
||||||
BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
|
explicit BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
|
||||||
virtual ~BasicRoutingInterface(){ };
|
virtual ~BasicRoutingInterface(){ };
|
||||||
|
|
||||||
inline void RoutingStep(
|
inline void RoutingStep(
|
||||||
@@ -62,57 +62,58 @@ public:
|
|||||||
SearchEngineData::QueryHeap & reverse_heap,
|
SearchEngineData::QueryHeap & reverse_heap,
|
||||||
NodeID * middle_node_id,
|
NodeID * middle_node_id,
|
||||||
int * upper_bound,
|
int * upper_bound,
|
||||||
const int edge_expansion_offset,
|
|
||||||
const bool forward_direction
|
const bool forward_direction
|
||||||
) const {
|
) const
|
||||||
|
{
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
const int distance = forward_heap.GetKey(node);
|
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;
|
const int new_distance = reverse_heap.GetKey(node) + distance;
|
||||||
if(new_distance < *upper_bound ){
|
if(new_distance < *upper_bound )
|
||||||
if( new_distance >= 0 ) {
|
{
|
||||||
|
if (new_distance >= 0)
|
||||||
|
{
|
||||||
*middle_node_id = node;
|
*middle_node_id = node;
|
||||||
*upper_bound = new_distance;
|
*upper_bound = new_distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (distance-edge_expansion_offset) > *upper_bound ){
|
if (distance > *upper_bound)
|
||||||
|
{
|
||||||
forward_heap.DeleteAll();
|
forward_heap.DeleteAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Stalling
|
//Stalling
|
||||||
for(
|
for (EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); ++edge)
|
||||||
EdgeID edge = facade->BeginEdges( node );
|
{
|
||||||
edge < facade->EndEdges(node);
|
|
||||||
++edge
|
|
||||||
) {
|
|
||||||
const EdgeData & data = facade->GetEdgeData(edge);
|
const EdgeData & data = facade->GetEdgeData(edge);
|
||||||
const bool reverse_flag = (!forward_direction) ? data.forward : data.backward;
|
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
||||||
if( reverse_flag ) {
|
if (reverse_flag)
|
||||||
|
{
|
||||||
const NodeID to = facade->GetTarget(edge);
|
const NodeID to = facade->GetTarget(edge);
|
||||||
const int edge_weight = data.distance;
|
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.WasInserted(to))
|
||||||
if(forward_heap.GetKey( to ) + edge_weight < distance) {
|
{
|
||||||
|
if(forward_heap.GetKey( to ) + edge_weight < distance)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(
|
for (EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); edge < end_edge; ++edge)
|
||||||
EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node);
|
{
|
||||||
edge < end_edge;
|
|
||||||
++edge
|
|
||||||
) {
|
|
||||||
const EdgeData & data = facade->GetEdgeData(edge);
|
const EdgeData & data = facade->GetEdgeData(edge);
|
||||||
bool forward_directionFlag = (forward_direction ? data.forward : data.backward );
|
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
||||||
if( forward_directionFlag ) {
|
if (forward_directionFlag)
|
||||||
|
{
|
||||||
|
|
||||||
const NodeID to = facade->GetTarget(edge);
|
const NodeID to = facade->GetTarget(edge);
|
||||||
const int edge_weight = data.distance;
|
const int edge_weight = data.distance;
|
||||||
@@ -126,18 +127,19 @@ public:
|
|||||||
}
|
}
|
||||||
//Found a shorter Path -> Update distance
|
//Found a shorter Path -> Update distance
|
||||||
else if ( to_distance < forward_heap.GetKey( to ) ) {
|
else if ( to_distance < forward_heap.GetKey( to ) ) {
|
||||||
|
//new parent
|
||||||
forward_heap.GetData( to ).parent = node;
|
forward_heap.GetData( to ).parent = node;
|
||||||
forward_heap.DecreaseKey( to, to_distance );
|
forward_heap.DecreaseKey( to, to_distance );
|
||||||
//new parent
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void UnpackPath(
|
inline void UnpackPath(const std::vector<NodeID> & packed_path, const PhantomNodes & phantom_node_pair, std::vector<PathData> & unpacked_path) const
|
||||||
const std::vector<NodeID> & packed_path,
|
{
|
||||||
std::vector<PathData> & unpacked_path
|
const bool start_traversed_in_reverse = (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
|
||||||
) const {
|
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();
|
const unsigned packed_path_size = packed_path.size();
|
||||||
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||||
|
|
||||||
@@ -149,87 +151,170 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::pair<NodeID, NodeID> edge;
|
std::pair<NodeID, NodeID> edge;
|
||||||
while(!recursion_stack.empty()) {
|
while (!recursion_stack.empty())
|
||||||
|
{
|
||||||
edge = recursion_stack.top();
|
edge = recursion_stack.top();
|
||||||
recursion_stack.pop();
|
recursion_stack.pop();
|
||||||
|
|
||||||
|
// facade->FindEdge does not suffice here in case of shortcuts.
|
||||||
|
// The above explanation unclear? Think!
|
||||||
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||||
int edge_weight = INT_MAX;
|
int edge_weight = INT_MAX;
|
||||||
for(
|
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
||||||
EdgeID edge_id = facade->BeginEdges(edge.first);
|
{
|
||||||
edge_id < facade->EndEdges(edge.first);
|
|
||||||
++edge_id
|
|
||||||
){
|
|
||||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
if(
|
if ((facade->GetTarget(edge_id) == edge.second) &&
|
||||||
(facade->GetTarget(edge_id) == edge.second) &&
|
|
||||||
(weight < edge_weight) &&
|
(weight < edge_weight) &&
|
||||||
facade->GetEdgeData(edge_id).forward
|
facade->GetEdgeData(edge_id).forward)
|
||||||
){
|
{
|
||||||
smaller_edge_id = edge_id;
|
smaller_edge_id = edge_id;
|
||||||
edge_weight = weight;
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||||
if( SPECIAL_EDGEID == smaller_edge_id ){
|
{
|
||||||
for(
|
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
||||||
EdgeID edge_id = facade->BeginEdges(edge.second);
|
{
|
||||||
edge_id < facade->EndEdges(edge.second);
|
|
||||||
++edge_id
|
|
||||||
){
|
|
||||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
if(
|
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
||||||
(facade->GetTarget(edge_id) == edge.first) &&
|
{
|
||||||
(weight < edge_weight) &&
|
|
||||||
facade->GetEdgeData(edge_id).backward
|
|
||||||
){
|
|
||||||
smaller_edge_id = edge_id;
|
smaller_edge_id = edge_id;
|
||||||
edge_weight = weight;
|
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);
|
const EdgeData & ed = facade->GetEdgeData(smaller_edge_id);
|
||||||
if( ed.shortcut ) {//unpack
|
if (ed.shortcut)
|
||||||
|
{//unpack
|
||||||
const NodeID middle_node_id = ed.id;
|
const NodeID middle_node_id = ed.id;
|
||||||
//again, we need to this in reversed order
|
//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(middle_node_id, edge.second));
|
||||||
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
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(
|
unpacked_path.push_back(
|
||||||
PathData(
|
PathData(
|
||||||
ed.id,
|
id_vector[i],
|
||||||
facade->GetNameIndexFromEdgeID(ed.id),
|
phantom_node_pair.target_phantom.name_id,
|
||||||
facade->GetTurnInstructionForEdgeID(ed.id),
|
TurnInstructionsClass::NoTurn,
|
||||||
ed.distance
|
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(
|
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpacked_path) const
|
||||||
const NodeID s,
|
{
|
||||||
const NodeID t,
|
|
||||||
std::vector<NodeID> & unpacked_path
|
|
||||||
) const {
|
|
||||||
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||||
recursion_stack.push(std::make_pair(s,t));
|
recursion_stack.push(std::make_pair(s,t));
|
||||||
|
|
||||||
std::pair<NodeID, NodeID> edge;
|
std::pair<NodeID, NodeID> edge;
|
||||||
while(!recursion_stack.empty()) {
|
while (!recursion_stack.empty())
|
||||||
|
{
|
||||||
edge = recursion_stack.top();
|
edge = recursion_stack.top();
|
||||||
recursion_stack.pop();
|
recursion_stack.pop();
|
||||||
|
|
||||||
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||||
int edge_weight = INT_MAX;
|
int edge_weight = INT_MAX;
|
||||||
for(
|
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
||||||
EdgeID edge_id = facade->BeginEdges(edge.first);
|
{
|
||||||
edge_id < facade->EndEdges(edge.first);
|
|
||||||
++edge_id
|
|
||||||
){
|
|
||||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
if(
|
if(
|
||||||
(facade->GetTarget(edge_id) == edge.second) &&
|
(facade->GetTarget(edge_id) == edge.second) &&
|
||||||
@@ -241,18 +326,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( SPECIAL_EDGEID == smaller_edge_id ){
|
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||||
for(
|
{
|
||||||
EdgeID edge_id = facade->BeginEdges(edge.second);
|
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
||||||
edge_id < facade->EndEdges(edge.second);
|
{
|
||||||
++edge_id
|
|
||||||
){
|
|
||||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
if(
|
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
||||||
(facade->GetTarget(edge_id) == edge.first) &&
|
{
|
||||||
(weight < edge_weight) &&
|
|
||||||
facade->GetEdgeData(edge_id).backward
|
|
||||||
){
|
|
||||||
smaller_edge_id = edge_id;
|
smaller_edge_id = edge_id;
|
||||||
edge_weight = weight;
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
@@ -261,16 +341,15 @@ public:
|
|||||||
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
|
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
|
||||||
|
|
||||||
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
||||||
if(ed.shortcut) {//unpack
|
if (ed.shortcut)
|
||||||
|
{//unpack
|
||||||
const NodeID middle_node_id = ed.id;
|
const NodeID middle_node_id = ed.id;
|
||||||
//again, we need to this in reversed order
|
//again, we need to this in reversed order
|
||||||
recursion_stack.push(
|
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
||||||
std::make_pair(middle_node_id, edge.second)
|
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
||||||
);
|
}
|
||||||
recursion_stack.push(
|
else
|
||||||
std::make_pair(edge.first, middle_node_id)
|
{
|
||||||
);
|
|
||||||
} else {
|
|
||||||
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
|
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
|
||||||
unpacked_path.push_back(edge.first );
|
unpacked_path.push_back(edge.first );
|
||||||
}
|
}
|
||||||
@@ -279,43 +358,41 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void RetrievePackedPathFromHeap(
|
inline void RetrievePackedPathFromHeap(
|
||||||
SearchEngineData::QueryHeap & forward_heap,
|
const SearchEngineData::QueryHeap & forward_heap,
|
||||||
SearchEngineData::QueryHeap & reverse_heap,
|
const SearchEngineData::QueryHeap & reverse_heap,
|
||||||
const NodeID middle_node_id,
|
const NodeID middle_node_id,
|
||||||
std::vector<NodeID> & packed_path
|
std::vector<NodeID> & packed_path
|
||||||
) const {
|
) const
|
||||||
|
{
|
||||||
NodeID current_node_id = middle_node_id;
|
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;
|
current_node_id = forward_heap.GetData(current_node_id).parent;
|
||||||
packed_path.push_back(current_node_id);
|
packed_path.push_back(current_node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::reverse(packed_path.begin(), packed_path.end());
|
std::reverse(packed_path.begin(), packed_path.end());
|
||||||
packed_path.push_back(middle_node_id);
|
packed_path.push_back(middle_node_id);
|
||||||
current_node_id = 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;
|
current_node_id = reverse_heap.GetData(current_node_id).parent;
|
||||||
packed_path.push_back(current_node_id);
|
packed_path.push_back(current_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: reorder parameters
|
|
||||||
inline void RetrievePackedPathFromSingleHeap(
|
inline void RetrievePackedPathFromSingleHeap(
|
||||||
SearchEngineData::QueryHeap & search_heap,
|
const SearchEngineData::QueryHeap & search_heap,
|
||||||
const NodeID middle_node_id,
|
const NodeID middle_node_id,
|
||||||
std::vector<NodeID>& packed_path
|
std::vector<NodeID>& packed_path
|
||||||
) const {
|
) const
|
||||||
|
{
|
||||||
NodeID current_node_id = middle_node_id;
|
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;
|
current_node_id = search_heap.GetData(current_node_id).parent;
|
||||||
packed_path.push_back(current_node_id);
|
packed_path.push_back(current_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ComputeEdgeOffset(const PhantomNode & phantom) const {
|
|
||||||
return phantom.weight1 + (phantom.isBidirected() ? phantom.weight2 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASICROUTINGINTERFACE_H_ */
|
#endif /* BASICROUTINGINTERFACE_H_ */
|
||||||
|
|||||||
@@ -48,21 +48,22 @@ public:
|
|||||||
) :
|
) :
|
||||||
super(facade),
|
super(facade),
|
||||||
engine_working_data(engine_working_data)
|
engine_working_data(engine_working_data)
|
||||||
{}
|
{ }
|
||||||
|
|
||||||
~ShortestPathRouting() {}
|
~ShortestPathRouting() { }
|
||||||
|
|
||||||
void operator()(
|
void operator()(
|
||||||
const std::vector<PhantomNodes> & phantom_nodes_vector,
|
const std::vector<PhantomNodes> & phantom_nodes_vector,
|
||||||
RawRouteData & raw_route_data
|
RawRouteData & raw_route_data
|
||||||
) const {
|
) const
|
||||||
|
{
|
||||||
BOOST_FOREACH(
|
BOOST_FOREACH(
|
||||||
const PhantomNodes & phantom_node_pair,
|
const PhantomNodes & phantom_node_pair,
|
||||||
phantom_nodes_vector
|
phantom_nodes_vector
|
||||||
){
|
){
|
||||||
if(!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
if( phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ) {
|
||||||
raw_route_data.lengthOfShortestPath = INT_MAX;
|
// raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||||
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
// raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,71 +105,84 @@ public:
|
|||||||
middle2 = UINT_MAX;
|
middle2 = UINT_MAX;
|
||||||
|
|
||||||
//insert new starting nodes into forward heap, adjusted by previous distances.
|
//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(
|
forward_heap1.Insert(
|
||||||
phantom_node_pair.startPhantom.edgeBasedNode,
|
phantom_node_pair.source_phantom.forward_node_id,
|
||||||
distance1-phantom_node_pair.startPhantom.weight1,
|
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||||
phantom_node_pair.startPhantom.edgeBasedNode
|
phantom_node_pair.source_phantom.forward_node_id
|
||||||
);
|
);
|
||||||
forward_heap2.Insert(
|
forward_heap2.Insert(
|
||||||
phantom_node_pair.startPhantom.edgeBasedNode,
|
phantom_node_pair.source_phantom.forward_node_id,
|
||||||
distance1-phantom_node_pair.startPhantom.weight1,
|
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||||
phantom_node_pair.startPhantom.edgeBasedNode
|
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(
|
forward_heap1.Insert(
|
||||||
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
phantom_node_pair.source_phantom.reverse_node_id,
|
||||||
distance2-phantom_node_pair.startPhantom.weight2,
|
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||||
phantom_node_pair.startPhantom.edgeBasedNode+1
|
phantom_node_pair.source_phantom.reverse_node_id
|
||||||
);
|
);
|
||||||
forward_heap2.Insert(
|
forward_heap2.Insert(
|
||||||
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
phantom_node_pair.source_phantom.reverse_node_id,
|
||||||
distance2-phantom_node_pair.startPhantom.weight2,
|
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||||
phantom_node_pair.startPhantom.edgeBasedNode+1
|
phantom_node_pair.source_phantom.reverse_node_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//insert new backward nodes into backward heap, unadjusted.
|
//insert new backward nodes into backward heap, unadjusted.
|
||||||
reverse_heap1.Insert(
|
if( phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID ) {
|
||||||
phantom_node_pair.targetPhantom.edgeBasedNode,
|
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset();
|
||||||
phantom_node_pair.targetPhantom.weight1,
|
reverse_heap1.Insert(
|
||||||
phantom_node_pair.targetPhantom.edgeBasedNode
|
phantom_node_pair.target_phantom.forward_node_id,
|
||||||
);
|
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
|
||||||
if(phantom_node_pair.targetPhantom.isBidirected() ) {
|
phantom_node_pair.target_phantom.forward_node_id
|
||||||
reverse_heap2.Insert(
|
|
||||||
phantom_node_pair.targetPhantom.edgeBasedNode+1,
|
|
||||||
phantom_node_pair.targetPhantom.weight2,
|
|
||||||
phantom_node_pair.targetPhantom.edgeBasedNode+1
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int forward_offset = super::ComputeEdgeOffset(
|
if( phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID ) {
|
||||||
phantom_node_pair.startPhantom
|
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset();
|
||||||
);
|
reverse_heap2.Insert(
|
||||||
const int reverse_offset = super::ComputeEdgeOffset(
|
phantom_node_pair.target_phantom.reverse_node_id,
|
||||||
phantom_node_pair.targetPhantom
|
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.
|
//run two-Target Dijkstra routing step.
|
||||||
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
||||||
if( !forward_heap1.Empty()){
|
if( 0 < forward_heap1.Size() ){
|
||||||
super::RoutingStep(
|
super::RoutingStep(
|
||||||
forward_heap1,
|
forward_heap1,
|
||||||
reverse_heap1,
|
reverse_heap1,
|
||||||
&middle1,
|
&middle1,
|
||||||
&local_upper_bound1,
|
&local_upper_bound1,
|
||||||
forward_offset,
|
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if( !reverse_heap1.Empty() ){
|
if( 0 < reverse_heap1.Size() ){
|
||||||
super::RoutingStep(
|
super::RoutingStep(
|
||||||
reverse_heap1,
|
reverse_heap1,
|
||||||
forward_heap1,
|
forward_heap1,
|
||||||
&middle1,
|
&middle1,
|
||||||
&local_upper_bound1,
|
&local_upper_bound1,
|
||||||
reverse_offset,
|
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -176,23 +190,21 @@ public:
|
|||||||
|
|
||||||
if( !reverse_heap2.Empty() ) {
|
if( !reverse_heap2.Empty() ) {
|
||||||
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
||||||
if( !forward_heap2.Empty() ){
|
if( 0 < forward_heap2.Size() ){
|
||||||
super::RoutingStep(
|
super::RoutingStep(
|
||||||
forward_heap2,
|
forward_heap2,
|
||||||
reverse_heap2,
|
reverse_heap2,
|
||||||
&middle2,
|
&middle2,
|
||||||
&local_upper_bound2,
|
&local_upper_bound2,
|
||||||
forward_offset,
|
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if( !reverse_heap2.Empty() ){
|
if( 0 < reverse_heap2.Size() ){
|
||||||
super::RoutingStep(
|
super::RoutingStep(
|
||||||
reverse_heap2,
|
reverse_heap2,
|
||||||
forward_heap2,
|
forward_heap2,
|
||||||
&middle2,
|
&middle2,
|
||||||
&local_upper_bound2,
|
&local_upper_bound2,
|
||||||
reverse_offset,
|
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -201,17 +213,17 @@ public:
|
|||||||
|
|
||||||
//No path found for both target nodes?
|
//No path found for both target nodes?
|
||||||
if(
|
if(
|
||||||
(INT_MAX == local_upper_bound1) &&
|
(INVALID_EDGE_WEIGHT == local_upper_bound1) &&
|
||||||
(INT_MAX == local_upper_bound2)
|
(INVALID_EDGE_WEIGHT == local_upper_bound2)
|
||||||
) {
|
) {
|
||||||
raw_route_data.lengthOfShortestPath = INT_MAX;
|
raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT;
|
||||||
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(UINT_MAX == middle1) {
|
if( SPECIAL_NODEID == middle1 ) {
|
||||||
search_from_1st_node = false;
|
search_from_1st_node = false;
|
||||||
}
|
}
|
||||||
if(UINT_MAX == middle2) {
|
if( SPECIAL_NODEID == middle2 ) {
|
||||||
search_from_2nd_node = false;
|
search_from_2nd_node = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +240,7 @@ public:
|
|||||||
BOOST_ASSERT( (unsigned)current_leg < packed_legs1.size() );
|
BOOST_ASSERT( (unsigned)current_leg < packed_legs1.size() );
|
||||||
BOOST_ASSERT( (unsigned)current_leg < packed_legs2.size() );
|
BOOST_ASSERT( (unsigned)current_leg < packed_legs2.size() );
|
||||||
|
|
||||||
if(INT_MAX != local_upper_bound1) {
|
if( INVALID_EDGE_WEIGHT != local_upper_bound1 ) {
|
||||||
super::RetrievePackedPathFromHeap(
|
super::RetrievePackedPathFromHeap(
|
||||||
forward_heap1,
|
forward_heap1,
|
||||||
reverse_heap1,
|
reverse_heap1,
|
||||||
@@ -237,7 +249,7 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(INT_MAX != local_upper_bound2) {
|
if( INVALID_EDGE_WEIGHT != local_upper_bound2 ) {
|
||||||
super::RetrievePackedPathFromHeap(
|
super::RetrievePackedPathFromHeap(
|
||||||
forward_heap2,
|
forward_heap2,
|
||||||
reverse_heap2,
|
reverse_heap2,
|
||||||
@@ -264,8 +276,6 @@ public:
|
|||||||
local_upper_bound2 = local_upper_bound1;
|
local_upper_bound2 = local_upper_bound1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimpleLogger().Write() << "fetched packed paths";
|
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(
|
||||||
!temporary_packed_leg1.empty() ||
|
!temporary_packed_leg1.empty() ||
|
||||||
!temporary_packed_leg2.empty(),
|
!temporary_packed_leg2.empty(),
|
||||||
@@ -335,11 +345,11 @@ public:
|
|||||||
|
|
||||||
if(
|
if(
|
||||||
(packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
|
(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();
|
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_1st_node &= !(last_node_id == phantom_node_pair.target_phantom.reverse_node_id);
|
||||||
search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode);
|
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 );
|
BOOST_ASSERT( search_from_1st_node != search_from_2nd_node );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,14 +358,42 @@ public:
|
|||||||
++current_leg;
|
++current_leg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( distance1 > distance2 ) {
|
if (distance1 > distance2)
|
||||||
|
{
|
||||||
std::swap( packed_legs1, packed_legs2 );
|
std::swap( packed_legs1, packed_legs2 );
|
||||||
}
|
}
|
||||||
raw_route_data.unpacked_path_segments.resize( packed_legs1.size() );
|
raw_route_data.unpacked_path_segments.resize( packed_legs1.size() );
|
||||||
for(unsigned i = 0; i < packed_legs1.size(); ++i){
|
// 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;
|
||||||
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size() );
|
|
||||||
|
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(
|
super::UnpackPath(
|
||||||
|
// -- packed input
|
||||||
packed_legs1[i],
|
packed_legs1[i],
|
||||||
|
// -- start and end of (sub-)route
|
||||||
|
unpack_phantom_node_pair,
|
||||||
|
// -- unpacked output
|
||||||
raw_route_data.unpacked_path_segments[i]
|
raw_route_data.unpacked_path_segments[i]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ namespace qi = boost::spirit::qi;
|
|||||||
|
|
||||||
template <typename Iterator, class HandlerT>
|
template <typename Iterator, class HandlerT>
|
||||||
struct APIGrammar : qi::grammar<Iterator> {
|
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);
|
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) ) ;
|
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,15 @@ public:
|
|||||||
const unsigned id
|
const unsigned id
|
||||||
) const = 0;
|
) 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(
|
virtual TurnInstruction GetTurnInstructionForEdgeID(
|
||||||
const unsigned id
|
const unsigned id
|
||||||
) const = 0;
|
) const = 0;
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
template<class EdgeDataT>
|
template<class EdgeDataT>
|
||||||
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
|
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
|
||||||
|
|
||||||
@@ -61,14 +64,23 @@ private:
|
|||||||
QueryGraph * m_query_graph;
|
QueryGraph * m_query_graph;
|
||||||
std::string m_timestamp;
|
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<NodeID, false>::vector m_via_node_list;
|
||||||
ShM<unsigned, false>::vector m_name_ID_list;
|
ShM<unsigned, false>::vector m_name_ID_list;
|
||||||
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
|
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
|
||||||
ShM<char, false>::vector m_names_char_list;
|
ShM<char, false>::vector m_names_char_list;
|
||||||
ShM<unsigned, false>::vector m_name_begin_indices;
|
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) {
|
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 != 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";
|
SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() << " edges";
|
||||||
m_query_graph = new QueryGraph(node_list, edge_list);
|
m_query_graph = new QueryGraph(node_list, edge_list);
|
||||||
|
|
||||||
@@ -113,42 +125,44 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LoadNodeAndEdgeInformation(
|
void LoadNodeAndEdgeInformation(
|
||||||
const boost::filesystem::path nodes_file,
|
const boost::filesystem::path & nodes_file,
|
||||||
const boost::filesystem::path edges_file
|
const boost::filesystem::path & edges_file
|
||||||
) {
|
) {
|
||||||
boost::filesystem::ifstream nodes_input_stream(
|
boost::filesystem::ifstream nodes_input_stream(
|
||||||
nodes_file,
|
nodes_file,
|
||||||
std::ios::binary
|
std::ios::binary
|
||||||
);
|
);
|
||||||
|
|
||||||
SimpleLogger().Write(logDEBUG) << "Loading node data";
|
|
||||||
NodeInfo current_node;
|
NodeInfo current_node;
|
||||||
unsigned number_of_coordinates = 0;
|
unsigned number_of_coordinates = 0;
|
||||||
nodes_input_stream.read(
|
nodes_input_stream.read(
|
||||||
(char *)&number_of_coordinates,
|
(char *)&number_of_coordinates,
|
||||||
sizeof(unsigned)
|
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) {
|
for(unsigned i = 0; i < number_of_coordinates; ++i) {
|
||||||
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
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.lat,
|
||||||
current_node.lon
|
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();
|
nodes_input_stream.close();
|
||||||
|
|
||||||
SimpleLogger().Write(logDEBUG) << "Loading edge data";
|
|
||||||
boost::filesystem::ifstream edges_input_stream(
|
boost::filesystem::ifstream edges_input_stream(
|
||||||
edges_file,
|
edges_file,
|
||||||
std::ios::binary
|
std::ios::binary
|
||||||
);
|
);
|
||||||
unsigned number_of_edges = 0;
|
unsigned number_of_edges = 0;
|
||||||
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
|
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
|
||||||
m_via_node_list.resize(number_of_edges);
|
m_via_node_list.resize (number_of_edges);
|
||||||
m_name_ID_list.resize(number_of_edges);
|
m_name_ID_list.resize (number_of_edges);
|
||||||
m_turn_instruction_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;
|
OriginalEdgeData current_edge_data;
|
||||||
for(unsigned i = 0; i < number_of_edges; ++i) {
|
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_via_node_list[i] = current_edge_data.via_node;
|
||||||
m_name_ID_list[i] = current_edge_data.name_id;
|
m_name_ID_list[i] = current_edge_data.name_id;
|
||||||
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
|
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();
|
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(
|
void LoadRTree(
|
||||||
const boost::filesystem::path & ram_index_path,
|
const boost::filesystem::path & ram_index_path,
|
||||||
const boost::filesystem::path & file_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,
|
ram_index_path,
|
||||||
file_index_path
|
file_index_path,
|
||||||
|
m_coordinate_list
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,10 +264,10 @@ private:
|
|||||||
public:
|
public:
|
||||||
~InternalDataFacade() {
|
~InternalDataFacade() {
|
||||||
delete m_query_graph;
|
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
|
//generate paths of data files
|
||||||
if( server_paths.find("hsgrdata") == server_paths.end() ) {
|
if( server_paths.find("hsgrdata") == server_paths.end() ) {
|
||||||
throw OSRMException("no hsgr file given in ini file");
|
throw OSRMException("no hsgr file given in ini file");
|
||||||
@@ -218,6 +278,9 @@ public:
|
|||||||
if( server_paths.find("fileindex") == server_paths.end() ) {
|
if( server_paths.find("fileindex") == server_paths.end() ) {
|
||||||
throw OSRMException("no leaf index file given in ini file");
|
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() ) {
|
if( server_paths.find("nodesdata") == server_paths.end() ) {
|
||||||
throw OSRMException("no nodes file given in ini file");
|
throw OSRMException("no nodes file given in ini file");
|
||||||
}
|
}
|
||||||
@@ -249,12 +312,17 @@ public:
|
|||||||
paths_iterator = server_paths.find("namesdata");
|
paths_iterator = server_paths.find("namesdata");
|
||||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
const boost::filesystem::path & names_data_path = paths_iterator->second;
|
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
|
//load data
|
||||||
SimpleLogger().Write() << "loading graph data";
|
SimpleLogger().Write() << "loading graph data";
|
||||||
LoadGraph(hsgr_path);
|
LoadGraph(hsgr_path);
|
||||||
SimpleLogger().Write() << "loading egde information";
|
SimpleLogger().Write() << "loading egde information";
|
||||||
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
|
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
|
||||||
|
SimpleLogger().Write() << "loading geometries";
|
||||||
|
LoadGeometries( geometries_path );
|
||||||
SimpleLogger().Write() << "loading r-tree";
|
SimpleLogger().Write() << "loading r-tree";
|
||||||
LoadRTree(ram_index_path, file_index_path);
|
LoadRTree(ram_index_path, file_index_path);
|
||||||
SimpleLogger().Write() << "loading timestamp";
|
SimpleLogger().Write() << "loading timestamp";
|
||||||
@@ -319,10 +387,13 @@ public:
|
|||||||
FixedPointCoordinate GetCoordinateOfNode(
|
FixedPointCoordinate GetCoordinateOfNode(
|
||||||
const unsigned id
|
const unsigned id
|
||||||
) const {
|
) const {
|
||||||
const NodeID node = m_via_node_list.at(id);
|
return m_coordinate_list->at(id);
|
||||||
return m_coordinate_list.at(node);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool EdgeIsCompressed( const unsigned id ) const {
|
||||||
|
return m_egde_is_compressed.at(id);
|
||||||
|
}
|
||||||
|
|
||||||
TurnInstruction GetTurnInstructionForEdgeID(
|
TurnInstruction GetTurnInstructionForEdgeID(
|
||||||
const unsigned id
|
const unsigned id
|
||||||
) const {
|
) const {
|
||||||
@@ -346,11 +417,12 @@ public:
|
|||||||
PhantomNode & resulting_phantom_node,
|
PhantomNode & resulting_phantom_node,
|
||||||
const unsigned zoom_level
|
const unsigned zoom_level
|
||||||
) const {
|
) const {
|
||||||
return m_static_rtree->FindPhantomNodeForCoordinate(
|
const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
resulting_phantom_node,
|
resulting_phantom_node,
|
||||||
zoom_level
|
zoom_level
|
||||||
);
|
);
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetCheckSum() const { return m_check_sum; }
|
unsigned GetCheckSum() const { return m_check_sum; }
|
||||||
@@ -368,8 +440,8 @@ public:
|
|||||||
name_id < m_name_begin_indices.size(),
|
name_id < m_name_begin_indices.size(),
|
||||||
"name id too high"
|
"name id too high"
|
||||||
);
|
);
|
||||||
unsigned begin_index = m_name_begin_indices[name_id];
|
const unsigned begin_index = m_name_begin_indices[name_id];
|
||||||
unsigned end_index = m_name_begin_indices[name_id+1];
|
const unsigned end_index = m_name_begin_indices[name_id+1];
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(
|
||||||
begin_index < m_names_char_list.size(),
|
begin_index < m_names_char_list.size(),
|
||||||
"begin index of name too high"
|
"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 {
|
std::string GetTimestamp() const {
|
||||||
return m_timestamp;
|
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
|
//implements all data storage when shared memory _IS_ used
|
||||||
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "BaseDataFacade.h"
|
#include "BaseDataFacade.h"
|
||||||
#include "SharedDataType.h"
|
#include "SharedDataType.h"
|
||||||
|
|
||||||
@@ -42,6 +39,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../../Util/ProgramOptions.h"
|
#include "../../Util/ProgramOptions.h"
|
||||||
#include "../../Util/SimpleLogger.h"
|
#include "../../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
template<class EdgeDataT>
|
template<class EdgeDataT>
|
||||||
@@ -55,7 +55,7 @@ private:
|
|||||||
typedef typename StaticGraph<EdgeData, true>::_StrEdge GraphEdge;
|
typedef typename StaticGraph<EdgeData, true>::_StrEdge GraphEdge;
|
||||||
typedef typename QueryGraph::InputEdge InputEdge;
|
typedef typename QueryGraph::InputEdge InputEdge;
|
||||||
typedef typename super::RTreeLeaf RTreeLeaf;
|
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;
|
SharedDataLayout * data_layout;
|
||||||
char * shared_memory;
|
char * shared_memory;
|
||||||
@@ -72,15 +72,25 @@ private:
|
|||||||
boost::shared_ptr<SharedMemory> m_large_memory;
|
boost::shared_ptr<SharedMemory> m_large_memory;
|
||||||
std::string m_timestamp;
|
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<NodeID, true>::vector m_via_node_list;
|
||||||
ShM<unsigned, true>::vector m_name_ID_list;
|
ShM<unsigned, true>::vector m_name_ID_list;
|
||||||
ShM<TurnInstruction, true>::vector m_turn_instruction_list;
|
ShM<TurnInstruction, true>::vector m_turn_instruction_list;
|
||||||
ShM<char, true>::vector m_names_char_list;
|
ShM<char, true>::vector m_names_char_list;
|
||||||
ShM<unsigned, true>::vector m_name_begin_indices;
|
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() {
|
void LoadTimestamp() {
|
||||||
char * timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset();
|
char * timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset();
|
||||||
@@ -95,13 +105,19 @@ private:
|
|||||||
void LoadRTree(
|
void LoadRTree(
|
||||||
const boost::filesystem::path & file_index_path
|
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 *)(
|
RTreeNode * tree_ptr = (RTreeNode *)(
|
||||||
shared_memory + data_layout->GetRSearchTreeOffset()
|
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,
|
tree_ptr,
|
||||||
data_layout->r_search_tree_size,
|
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 *)(
|
GraphEdge * graph_edges_ptr = (GraphEdge *)(
|
||||||
shared_memory + data_layout->GetGraphEdgeListOffsett()
|
shared_memory + data_layout->GetGraphEdgeListOffset()
|
||||||
);
|
);
|
||||||
|
|
||||||
typename ShM<GraphNode, true>::vector node_list(
|
typename ShM<GraphNode, true>::vector node_list(
|
||||||
@@ -126,7 +142,6 @@ private:
|
|||||||
m_query_graph.reset(
|
m_query_graph.reset(
|
||||||
new QueryGraph(node_list, edge_list)
|
new QueryGraph(node_list, edge_list)
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadNodeAndEdgeInformation() {
|
void LoadNodeAndEdgeInformation() {
|
||||||
@@ -134,11 +149,10 @@ private:
|
|||||||
FixedPointCoordinate * coordinate_list_ptr = (FixedPointCoordinate *)(
|
FixedPointCoordinate * coordinate_list_ptr = (FixedPointCoordinate *)(
|
||||||
shared_memory + data_layout->GetCoordinateListOffset()
|
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,
|
coordinate_list_ptr,
|
||||||
data_layout->coordinate_list_size
|
data_layout->coordinate_list_size
|
||||||
);
|
);
|
||||||
m_coordinate_list.swap( coordinate_list );
|
|
||||||
|
|
||||||
TurnInstruction * turn_instruction_list_ptr = (TurnInstruction *)(
|
TurnInstruction * turn_instruction_list_ptr = (TurnInstruction *)(
|
||||||
shared_memory + data_layout->GetTurnInstructionListOffset()
|
shared_memory + data_layout->GetTurnInstructionListOffset()
|
||||||
@@ -190,6 +204,36 @@ private:
|
|||||||
m_names_char_list.swap(names_char_list);
|
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:
|
public:
|
||||||
SharedDataFacade( ) {
|
SharedDataFacade( ) {
|
||||||
data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
|
data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
|
||||||
@@ -241,6 +285,7 @@ public:
|
|||||||
|
|
||||||
LoadGraph();
|
LoadGraph();
|
||||||
LoadNodeAndEdgeInformation();
|
LoadNodeAndEdgeInformation();
|
||||||
|
LoadGeometries();
|
||||||
LoadRTree(ram_index_path);
|
LoadRTree(ram_index_path);
|
||||||
LoadTimestamp();
|
LoadTimestamp();
|
||||||
LoadViaNodeList();
|
LoadViaNodeList();
|
||||||
@@ -250,7 +295,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//search graph access
|
//search graph access
|
||||||
unsigned GetNumberOfNodes() const {
|
unsigned GetNumberOfNodes() const {
|
||||||
return m_query_graph->GetNumberOfNodes();
|
return m_query_graph->GetNumberOfNodes();
|
||||||
@@ -307,10 +351,29 @@ public:
|
|||||||
FixedPointCoordinate GetCoordinateOfNode(
|
FixedPointCoordinate GetCoordinateOfNode(
|
||||||
const unsigned id
|
const unsigned id
|
||||||
) const {
|
) const {
|
||||||
const NodeID node = m_via_node_list.at(id);
|
return m_coordinate_list->at(id);
|
||||||
return m_coordinate_list.at(node);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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(
|
TurnInstruction GetTurnInstructionForEdgeID(
|
||||||
const unsigned id
|
const unsigned id
|
||||||
) const {
|
) const {
|
||||||
@@ -334,11 +397,12 @@ public:
|
|||||||
PhantomNode & resulting_phantom_node,
|
PhantomNode & resulting_phantom_node,
|
||||||
const unsigned zoom_level
|
const unsigned zoom_level
|
||||||
) const {
|
) const {
|
||||||
return m_static_rtree->FindPhantomNodeForCoordinate(
|
const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
resulting_phantom_node,
|
resulting_phantom_node,
|
||||||
zoom_level
|
zoom_level
|
||||||
);
|
);
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetCheckSum() const { return m_check_sum; }
|
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>
|
#include <boost/integer.hpp>
|
||||||
|
|
||||||
typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf;
|
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;
|
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||||
|
|
||||||
struct SharedDataLayout {
|
struct SharedDataLayout {
|
||||||
@@ -56,6 +56,9 @@ struct SharedDataLayout {
|
|||||||
uint64_t coordinate_list_size;
|
uint64_t coordinate_list_size;
|
||||||
uint64_t turn_instruction_list_size;
|
uint64_t turn_instruction_list_size;
|
||||||
uint64_t r_search_tree_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 checksum;
|
||||||
unsigned timestamp_length;
|
unsigned timestamp_length;
|
||||||
@@ -72,8 +75,12 @@ struct SharedDataLayout {
|
|||||||
coordinate_list_size(0),
|
coordinate_list_size(0),
|
||||||
turn_instruction_list_size(0),
|
turn_instruction_list_size(0),
|
||||||
r_search_tree_size(0),
|
r_search_tree_size(0),
|
||||||
|
geometries_index_list_size(0),
|
||||||
|
geometries_list_size(0),
|
||||||
|
geometries_indicators(0),
|
||||||
checksum(0),
|
checksum(0),
|
||||||
timestamp_length(0)
|
timestamp_length(0)
|
||||||
|
|
||||||
{
|
{
|
||||||
ram_index_file_name[0] = '\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) << "coordinate_list_size: " << coordinate_list_size;
|
||||||
SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << turn_instruction_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) << "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) << "sizeof(checksum): " << sizeof(checksum);
|
||||||
SimpleLogger().Write(logDEBUG) << "ram index file name: " << ram_index_file_name;
|
SimpleLogger().Write(logDEBUG) << "ram index file name: " << ram_index_file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GetSizeOfLayout() const {
|
uint64_t GetSizeOfLayout() const {
|
||||||
uint64_t result =
|
uint64_t result =
|
||||||
(name_index_list_size * sizeof(unsigned) ) +
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
(name_char_list_size * sizeof(char) ) +
|
(name_char_list_size * sizeof(char) ) +
|
||||||
(name_id_list_size * sizeof(unsigned) ) +
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
(via_node_list_size * sizeof(NodeID) ) +
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
|
||||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
|
||||||
(timestamp_length * sizeof(char) ) +
|
(timestamp_length * sizeof(char) ) +
|
||||||
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
|
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
|
||||||
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
|
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
|
||||||
(r_search_tree_size * sizeof(RTreeNode) ) +
|
(r_search_tree_size * sizeof(RTreeNode) ) +
|
||||||
sizeof(checksum) +
|
(geometries_indicators/32 + 1) * sizeof(unsigned) +
|
||||||
|
(geometries_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(geometries_list_size * sizeof(unsigned) ) +
|
||||||
|
sizeof(checksum) +
|
||||||
1024*sizeof(char);
|
1024*sizeof(char);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -140,10 +153,10 @@ struct SharedDataLayout {
|
|||||||
(via_node_list_size * sizeof(NodeID) );
|
(via_node_list_size * sizeof(NodeID) );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
uint64_t GetGraphEdgeListOffsett() const {
|
uint64_t GetGraphEdgeListOffset() const {
|
||||||
uint64_t result =
|
uint64_t result =
|
||||||
(name_index_list_size * sizeof(unsigned) ) +
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
(name_char_list_size * sizeof(char) ) +
|
(name_char_list_size * sizeof(char) ) +
|
||||||
(name_id_list_size * sizeof(unsigned) ) +
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
(via_node_list_size * sizeof(NodeID) ) +
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) ;
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) ;
|
||||||
@@ -184,29 +197,79 @@ struct SharedDataLayout {
|
|||||||
}
|
}
|
||||||
uint64_t GetRSearchTreeOffset() const {
|
uint64_t GetRSearchTreeOffset() const {
|
||||||
uint64_t result =
|
uint64_t result =
|
||||||
(name_index_list_size * sizeof(unsigned) ) +
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
(name_char_list_size * sizeof(char) ) +
|
(name_char_list_size * sizeof(char) ) +
|
||||||
(name_id_list_size * sizeof(unsigned) ) +
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
(via_node_list_size * sizeof(NodeID) ) +
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
|
||||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
|
||||||
(timestamp_length * sizeof(char) ) +
|
(timestamp_length * sizeof(char) ) +
|
||||||
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
|
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
|
||||||
(turn_instruction_list_size * sizeof(TurnInstructions) );
|
(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;
|
return result;
|
||||||
}
|
}
|
||||||
uint64_t GetChecksumOffset() const {
|
uint64_t GetChecksumOffset() const {
|
||||||
uint64_t result =
|
uint64_t result =
|
||||||
(name_index_list_size * sizeof(unsigned) ) +
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
(name_char_list_size * sizeof(char) ) +
|
(name_char_list_size * sizeof(char) ) +
|
||||||
(name_id_list_size * sizeof(unsigned) ) +
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
(via_node_list_size * sizeof(NodeID) ) +
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
|
||||||
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
|
||||||
(timestamp_length * sizeof(char) ) +
|
(timestamp_length * sizeof(char) ) +
|
||||||
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
|
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
|
||||||
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
|
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
|
||||||
(r_search_tree_size * sizeof(RTreeNode) );
|
(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;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ namespace http {
|
|||||||
void Reply::setSize(const unsigned size) {
|
void Reply::setSize(const unsigned size) {
|
||||||
BOOST_FOREACH ( Header& h, headers) {
|
BOOST_FOREACH ( Header& h, headers) {
|
||||||
if("Content-Length" == h.name) {
|
if("Content-Length" == h.name) {
|
||||||
std::string sizeString;
|
|
||||||
intToString(size,h.value);
|
intToString(size,h.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,10 +73,10 @@ std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
|
|||||||
std::vector<boost::asio::const_buffer> buffers;
|
std::vector<boost::asio::const_buffer> buffers;
|
||||||
buffers.push_back(ToBuffer(status));
|
buffers.push_back(ToBuffer(status));
|
||||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
for (std::size_t i = 0; i < headers.size(); ++i) {
|
||||||
Header& h = headers[i];
|
Header& current_header = headers[i];
|
||||||
buffers.push_back(boost::asio::buffer(h.name));
|
buffers.push_back(boost::asio::buffer(current_header.name));
|
||||||
buffers.push_back(boost::asio::buffer(seperators));
|
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));
|
||||||
}
|
}
|
||||||
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;
|
Reply rep;
|
||||||
rep.status = status;
|
rep.status = status;
|
||||||
rep.content.clear();
|
rep.content.clear();
|
||||||
rep.content.push_back( ToString(status) );
|
rep.content.push_back(rep.ToString(status));
|
||||||
rep.headers.resize(3);
|
rep.headers.resize(3);
|
||||||
rep.headers[0].name = "Access-Control-Allow-Origin";
|
rep.headers[0].name = "Access-Control-Allow-Origin";
|
||||||
rep.headers[0].value = "*";
|
rep.headers[0].value = "*";
|
||||||
rep.headers[1].name = "Content-Length";
|
rep.headers[1].name = "Content-Length";
|
||||||
|
|
||||||
std::string s;
|
std::string size_string;
|
||||||
intToString(rep.content.size(), s);
|
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].name = "Content-Type";
|
||||||
rep.headers[2].value = "text/html";
|
rep.headers[2].value = "text/html";
|
||||||
return rep;
|
return rep;
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "APIGrammar.h"
|
#include "APIGrammar.h"
|
||||||
#include "RequestHandler.h"
|
#include "RequestHandler.h"
|
||||||
|
#include "Http/Request.h"
|
||||||
|
|
||||||
#include "../Library/OSRM.h"
|
#include "../Library/OSRM.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/Reply.h>
|
||||||
#include <osrm/RouteParameters.h>
|
#include <osrm/RouteParameters.h>
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
@@ -76,21 +78,15 @@ void RequestHandler::handle_request(const http::Request& req, http::Reply& rep){
|
|||||||
|
|
||||||
if ( !result || (it != request.end()) ) {
|
if ( !result || (it != request.end()) ) {
|
||||||
rep = http::Reply::StockReply(http::Reply::badRequest);
|
rep = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
|
rep.content.clear();
|
||||||
const int position = std::distance(request.begin(), it);
|
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;
|
std::string tmp_position_string;
|
||||||
intToString(position, 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(tmp_position_string);
|
||||||
rep.content.push_back("<br>");
|
rep.content.push_back("\"}");
|
||||||
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>");
|
|
||||||
} else {
|
} else {
|
||||||
//parsing done, lets call the right plugin to handle the request
|
//parsing done, lets call the right plugin to handle the request
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(
|
||||||
|
|||||||
@@ -28,10 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef REQUEST_HANDLER_H
|
#ifndef REQUEST_HANDLER_H
|
||||||
#define REQUEST_HANDLER_H
|
#define REQUEST_HANDLER_H
|
||||||
|
|
||||||
#include "Http/Request.h"
|
|
||||||
|
|
||||||
#include <osrm/Reply.h>
|
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -41,6 +37,11 @@ struct APIGrammar;
|
|||||||
struct RouteParameters;
|
struct RouteParameters;
|
||||||
class OSRM;
|
class OSRM;
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
class Reply;
|
||||||
|
struct Request;
|
||||||
|
}
|
||||||
|
|
||||||
class RequestHandler : private boost::noncopyable {
|
class RequestHandler : private boost::noncopyable {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
+142
-112
@@ -38,11 +38,13 @@ boost::tuple<boost::tribool, char*> RequestParser::Parse(
|
|||||||
Request& req,
|
Request& req,
|
||||||
char* begin,
|
char* begin,
|
||||||
char* end,
|
char* end,
|
||||||
http::CompressionType * compressionType
|
http::CompressionType * compressionType)
|
||||||
) {
|
{
|
||||||
while (begin != end) {
|
while (begin != end)
|
||||||
|
{
|
||||||
boost::tribool result = consume(req, *begin++, compressionType);
|
boost::tribool result = consume(req, *begin++, compressionType);
|
||||||
if (result || !result){
|
if (result || !result)
|
||||||
|
{
|
||||||
return boost::make_tuple(result, begin);
|
return boost::make_tuple(result, begin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,193 +52,216 @@ boost::tuple<boost::tribool, char*> RequestParser::Parse(
|
|||||||
return boost::make_tuple(result, begin);
|
return boost::make_tuple(result, begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::tribool RequestParser::consume(
|
boost::tribool RequestParser::consume(Request& req, char input, http::CompressionType * compressionType)
|
||||||
Request& req, char input,
|
{
|
||||||
http::CompressionType * compressionType
|
switch (state_)
|
||||||
) {
|
{
|
||||||
switch (state_) {
|
|
||||||
case method_start:
|
case method_start:
|
||||||
if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
if (!isChar(input) || isCTL(input) || isTSpecial(input))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
state_ = method;
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
}
|
||||||
|
state_ = method;
|
||||||
|
return boost::indeterminate;
|
||||||
case method:
|
case method:
|
||||||
if (input == ' ') {
|
if (input == ' ')
|
||||||
|
{
|
||||||
state_ = uri;
|
state_ = uri;
|
||||||
return boost::indeterminate;
|
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:
|
case uri_start:
|
||||||
if (isCTL(input)) {
|
if (isCTL(input))
|
||||||
|
{
|
||||||
return false;
|
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:
|
case uri:
|
||||||
if (input == ' ') {
|
if (input == ' ')
|
||||||
|
{
|
||||||
state_ = http_version_h;
|
state_ = http_version_h;
|
||||||
return boost::indeterminate;
|
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:
|
case http_version_h:
|
||||||
if (input == 'H') {
|
if (input == 'H')
|
||||||
|
{
|
||||||
state_ = http_version_t_1;
|
state_ = http_version_t_1;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case http_version_t_1:
|
case http_version_t_1:
|
||||||
if (input == 'T') {
|
if (input == 'T')
|
||||||
|
{
|
||||||
state_ = http_version_t_2;
|
state_ = http_version_t_2;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case http_version_t_2:
|
case http_version_t_2:
|
||||||
if (input == 'T') {
|
if (input == 'T')
|
||||||
|
{
|
||||||
state_ = http_version_p;
|
state_ = http_version_p;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case http_version_p:
|
case http_version_p:
|
||||||
if (input == 'P') {
|
if (input == 'P')
|
||||||
|
{
|
||||||
state_ = http_version_slash;
|
state_ = http_version_slash;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case http_version_slash:
|
case http_version_slash:
|
||||||
if (input == '/') {
|
if (input == '/')
|
||||||
|
{
|
||||||
state_ = http_version_major_start;
|
state_ = http_version_major_start;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case http_version_major_start:
|
case http_version_major_start:
|
||||||
if (isDigit(input)) {
|
if (isDigit(input))
|
||||||
|
{
|
||||||
state_ = http_version_major;
|
state_ = http_version_major;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case http_version_major:
|
case http_version_major:
|
||||||
if (input == '.') {
|
if (input == '.')
|
||||||
|
{
|
||||||
state_ = http_version_minor_start;
|
state_ = http_version_minor_start;
|
||||||
return boost::indeterminate;
|
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:
|
case http_version_minor_start:
|
||||||
if (isDigit(input)) {
|
if (isDigit(input))
|
||||||
|
{
|
||||||
state_ = http_version_minor;
|
state_ = http_version_minor;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case http_version_minor:
|
case http_version_minor:
|
||||||
if (input == '\r') {
|
if (input == '\r')
|
||||||
|
{
|
||||||
state_ = expecting_newline_1;
|
state_ = expecting_newline_1;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else if (isDigit(input)) {
|
}
|
||||||
|
if (isDigit(input))
|
||||||
|
{
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
}
|
}
|
||||||
else {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case expecting_newline_1:
|
case expecting_newline_1:
|
||||||
if (input == '\n') {
|
if (input == '\n')
|
||||||
|
{
|
||||||
state_ = header_line_start;
|
state_ = header_line_start;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case header_line_start:
|
case header_line_start:
|
||||||
if(header.name == "Accept-Encoding") {
|
if(header.name == "Accept-Encoding")
|
||||||
|
{
|
||||||
/* giving gzip precedence over deflate */
|
/* giving gzip precedence over deflate */
|
||||||
if(header.value.find("deflate") != std::string::npos)
|
if (header.value.find("deflate") != std::string::npos)
|
||||||
|
{
|
||||||
*compressionType = deflateRFC1951;
|
*compressionType = deflateRFC1951;
|
||||||
if(header.value.find("gzip") != std::string::npos)
|
}
|
||||||
|
if (header.value.find("gzip") != std::string::npos)
|
||||||
|
{
|
||||||
*compressionType = gzipRFC1952;
|
*compressionType = gzipRFC1952;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if("Referer" == header.name)
|
if ("Referer" == header.name)
|
||||||
|
{
|
||||||
req.referrer = header.value;
|
req.referrer = header.value;
|
||||||
|
}
|
||||||
|
|
||||||
if("User-Agent" == header.name)
|
if ("User-Agent" == header.name)
|
||||||
|
{
|
||||||
req.agent = header.value;
|
req.agent = header.value;
|
||||||
|
}
|
||||||
|
|
||||||
if (input == '\r') {
|
if (input == '\r')
|
||||||
|
{
|
||||||
state_ = expecting_newline_3;
|
state_ = expecting_newline_3;
|
||||||
return boost::indeterminate;
|
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:
|
case header_lws:
|
||||||
if (input == '\r') {
|
if (input == '\r')
|
||||||
|
{
|
||||||
state_ = expecting_newline_2;
|
state_ = expecting_newline_2;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else if (input == ' ' || input == '\t') {
|
}
|
||||||
|
if (input == ' ' || input == '\t')
|
||||||
|
{
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
}
|
}
|
||||||
else if (isCTL(input)) {
|
if (isCTL(input)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
state_ = header_value;
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
}
|
||||||
|
state_ = header_value;
|
||||||
|
return boost::indeterminate;
|
||||||
case header_name:
|
case header_name:
|
||||||
if (input == ':') {
|
if (input == ':')
|
||||||
|
{
|
||||||
state_ = space_before_header_value;
|
state_ = space_before_header_value;
|
||||||
return boost::indeterminate;
|
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:
|
case space_before_header_value:
|
||||||
if (input == ' ') {
|
if (input == ' ')
|
||||||
|
{
|
||||||
state_ = header_value;
|
state_ = header_value;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case header_value:
|
case header_value:
|
||||||
if (input == '\r') {
|
if (input == '\r')
|
||||||
|
{
|
||||||
state_ = expecting_newline_2;
|
state_ = expecting_newline_2;
|
||||||
return boost::indeterminate;
|
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:
|
case expecting_newline_2:
|
||||||
if (input == '\n') {
|
if (input == '\n')
|
||||||
|
{
|
||||||
state_ = header_line_start;
|
state_ = header_line_start;
|
||||||
return boost::indeterminate;
|
return boost::indeterminate;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
case expecting_newline_3:
|
case expecting_newline_3:
|
||||||
return (input == '\n');
|
return (input == '\n');
|
||||||
default:
|
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;
|
return c >= 0 && c <= 127;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool RequestParser::isCTL(int c) {
|
inline bool RequestParser::isCTL(int c)
|
||||||
|
{
|
||||||
return (c >= 0 && c <= 31) || (c == 127);
|
return (c >= 0 && c <= 31) || (c == 127);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool RequestParser::isTSpecial(int c) {
|
inline bool RequestParser::isTSpecial(int c)
|
||||||
switch (c) {
|
{
|
||||||
case '(': case ')': case '<': case '>': case '@':
|
switch (c)
|
||||||
case ',': case ';': case ':': case '\\': case '"':
|
{
|
||||||
case '/': case '[': case ']': case '?': case '=':
|
case '(': case ')': case '<': case '>': case '@':
|
||||||
case '{': case '}': case ' ': case '\t':
|
case ',': case ';': case ':': case '\\': case '"':
|
||||||
return true;
|
case '/': case '[': case ']': case '?': case '=':
|
||||||
default:
|
case '{': case '}': case ' ': case '\t':
|
||||||
return false;
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool RequestParser::isDigit(int c) {
|
inline bool RequestParser::isDigit(int c)
|
||||||
|
{
|
||||||
return c >= '0' && c <= '9';
|
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/asio.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
@@ -72,7 +73,7 @@ public:
|
|||||||
void Run() {
|
void Run() {
|
||||||
std::vector<boost::shared_ptr<boost::thread> > threads;
|
std::vector<boost::shared_ptr<boost::thread> > threads;
|
||||||
for (unsigned i = 0; i < threadPoolSize; ++i) {
|
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);
|
threads.push_back(thread);
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < threads.size(); ++i)
|
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 <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
typedef QueryEdge::EdgeData EdgeData;
|
typedef QueryEdge::EdgeData EdgeData;
|
||||||
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
||||||
|
|
||||||
std::vector<NodeInfo> internal_to_external_node_map;
|
std::vector<NodeInfo> internal_to_external_node_map;
|
||||||
std::vector<TurnRestriction> restrictions_vector;
|
std::vector<TurnRestriction> restrictions_vector;
|
||||||
std::vector<NodeID> bollard_node_IDs_vector;
|
std::vector<NodeID> bollard_node_IDs_vector;
|
||||||
std::vector<NodeID> traffic_light_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();
|
LogPolicy::GetInstance().Unmute();
|
||||||
if(argc < 3) {
|
if (argc < 3)
|
||||||
SimpleLogger().Write(logWARNING) <<
|
{
|
||||||
"usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
|
SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
try
|
||||||
"Using restrictions from file: " << argv[2];
|
{
|
||||||
std::ifstream restriction_ifstream(argv[2], std::ios::binary);
|
SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
|
||||||
const UUID uuid_orig;
|
std::ifstream restriction_ifstream(argv[2], std::ios::binary);
|
||||||
UUID uuid_loaded;
|
const UUID uuid_orig;
|
||||||
restriction_ifstream.read((char *) &uuid_loaded, sizeof(UUID));
|
UUID uuid_loaded;
|
||||||
|
restriction_ifstream.read((char *)&uuid_loaded, sizeof(UUID));
|
||||||
|
|
||||||
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
|
if (!uuid_loaded.TestGraphUtil(uuid_orig))
|
||||||
SimpleLogger().Write(logWARNING) <<
|
{
|
||||||
argv[2] << " was prepared with a different build. "
|
SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
|
||||||
"Reprocess to get rid of this warning.";
|
"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";
|
||||||
}
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
if(!restriction_ifstream.good()) {
|
{
|
||||||
throw OSRMException("Could not access <osrm-restrictions> files");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+142
-163
@@ -48,45 +48,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
const unsigned number_of_elements = 268435456;
|
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());
|
std::sort(timings_vector.begin(), timings_vector.end());
|
||||||
stats.min = timings_vector.front();
|
stats.min = timings_vector.front();
|
||||||
stats.max = timings_vector.back();
|
stats.max = timings_vector.back();
|
||||||
stats.med = timings_vector[timings_vector.size()/2];
|
stats.med = timings_vector[timings_vector.size() / 2];
|
||||||
double primary_sum = std::accumulate(
|
double primary_sum = std::accumulate(timings_vector.begin(), timings_vector.end(), 0.0);
|
||||||
timings_vector.begin(),
|
|
||||||
timings_vector.end(),
|
|
||||||
0.0
|
|
||||||
);
|
|
||||||
stats.mean = primary_sum / timings_vector.size();
|
stats.mean = primary_sum / timings_vector.size();
|
||||||
|
|
||||||
double primary_sq_sum = std::inner_product( timings_vector.begin(),
|
double primary_sq_sum = std::inner_product(
|
||||||
timings_vector.end(),
|
timings_vector.begin(), timings_vector.end(), timings_vector.begin(), 0.0);
|
||||||
timings_vector.begin(),
|
stats.dev = std::sqrt(primary_sq_sum / timings_vector.size() - (stats.mean * stats.mean));
|
||||||
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();
|
LogPolicy::GetInstance().Unmute();
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION << ", "
|
||||||
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
<< "compiled at " << __DATE__ << ", " __TIME__;
|
||||||
"compiled at " << __DATE__ << ", " __TIME__;
|
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
SimpleLogger().Write() << "Not supported on FreeBSD";
|
SimpleLogger().Write() << "Not supported on FreeBSD";
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( 1 == argc ) {
|
if (1 == argc)
|
||||||
SimpleLogger().Write(logWARNING) <<
|
{
|
||||||
"usage: " << argv[0] << " /path/on/device";
|
SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " /path/on/device";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,119 +89,105 @@ int main (int argc, char * argv[]) {
|
|||||||
test_path /= "osrm.tst";
|
test_path /= "osrm.tst";
|
||||||
SimpleLogger().Write(logDEBUG) << "temporary file: " << test_path.string();
|
SimpleLogger().Write(logDEBUG) << "temporary file: " << test_path.string();
|
||||||
|
|
||||||
try {
|
try
|
||||||
//create files for testing
|
{
|
||||||
if( 2 == argc) {
|
// create files for testing
|
||||||
//create file to test
|
if (2 == argc)
|
||||||
if( boost::filesystem::exists(test_path) ) {
|
{
|
||||||
|
// create file to test
|
||||||
|
if (boost::filesystem::exists(test_path))
|
||||||
|
{
|
||||||
throw OSRMException("Data file already exists");
|
throw OSRMException("Data file already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
double time1, time2;
|
double time1, time2;
|
||||||
int * random_array = new int[number_of_elements];
|
int *random_array = new int[number_of_elements];
|
||||||
std::generate (
|
std::generate(random_array, random_array + number_of_elements, std::rand);
|
||||||
random_array,
|
|
||||||
random_array+number_of_elements,
|
|
||||||
std::rand
|
|
||||||
);
|
|
||||||
#ifdef __APPLE__
|
#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_NOCACHE, 1);
|
||||||
fcntl(fileno(fd), F_RDAHEAD, 0);
|
fcntl(fileno(fd), F_RDAHEAD, 0);
|
||||||
time1 = get_timestamp();
|
time1 = get_timestamp();
|
||||||
write(
|
write(fileno(fd), (char *)random_array, number_of_elements * sizeof(unsigned));
|
||||||
fileno(fd),
|
|
||||||
(char*)random_array,
|
|
||||||
number_of_elements*sizeof(unsigned)
|
|
||||||
);
|
|
||||||
time2 = get_timestamp();
|
time2 = get_timestamp();
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
int f = open(
|
int f =
|
||||||
test_path.string().c_str(),
|
open(test_path.string().c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, S_IRWXU);
|
||||||
O_CREAT|O_TRUNC|O_WRONLY|O_SYNC,
|
|
||||||
S_IRWXU
|
|
||||||
);
|
|
||||||
time1 = get_timestamp();
|
time1 = get_timestamp();
|
||||||
int ret = write(
|
int ret = write(f, random_array, number_of_elements * sizeof(unsigned));
|
||||||
f,
|
if (-1 == ret)
|
||||||
random_array,
|
{
|
||||||
number_of_elements*sizeof(unsigned)
|
|
||||||
);
|
|
||||||
if(-1 == ret) {
|
|
||||||
throw OSRMException("could not write random data file");
|
throw OSRMException("could not write random data file");
|
||||||
}
|
}
|
||||||
time2 = get_timestamp();
|
time2 = get_timestamp();
|
||||||
close(f);
|
close(f);
|
||||||
#endif
|
#endif
|
||||||
delete[] random_array;
|
delete[] random_array;
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
SimpleLogger().Write(logDEBUG) << "writing raw 1GB took " << (time2 - time1) * 1000
|
||||||
"writing raw 1GB took " << (time2-time1)*1000 << "ms";
|
<< "ms";
|
||||||
SimpleLogger().Write() << "raw write performance: " <<
|
SimpleLogger().Write() << "raw write performance: " << std::setprecision(5)
|
||||||
std::setprecision(5) << std::fixed <<
|
<< std::fixed << 1024 * 1024 / ((time2 - time1) * 1000)
|
||||||
1024*1024/((time2-time1)*1000) << "MB/sec";
|
<< "MB/sec";
|
||||||
|
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
SimpleLogger().Write(logDEBUG)
|
||||||
"finished creation of random data. Flush disk cache now!";
|
<< "finished creation of random data. Flush disk cache now!";
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
|
|
||||||
//
|
//
|
||||||
// Run Non-Cached I/O benchmarks
|
// 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");
|
throw OSRMException("data file does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
double time1, time2;
|
double time1, time2;
|
||||||
//volatiles do not get optimized
|
// volatiles do not get optimized
|
||||||
Statistics stats;
|
Statistics stats;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
volatile unsigned single_block[1024];
|
volatile unsigned single_block[1024];
|
||||||
char * raw_array = new char[number_of_elements*sizeof(unsigned)];
|
char *raw_array = new char[number_of_elements * sizeof(unsigned)];
|
||||||
FILE * fd = fopen(test_path.string().c_str(), "r");
|
FILE *fd = fopen(test_path.string().c_str(), "r");
|
||||||
fcntl(fileno(fd), F_NOCACHE, 1);
|
fcntl(fileno(fd), F_NOCACHE, 1);
|
||||||
fcntl(fileno(fd), F_RDAHEAD, 0);
|
fcntl(fileno(fd), F_RDAHEAD, 0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
char * single_block = (char*) memalign(
|
char *single_block = (char *)memalign(512, 1024 * sizeof(unsigned));
|
||||||
512,
|
|
||||||
1024*sizeof(unsigned)
|
|
||||||
);
|
|
||||||
|
|
||||||
int f = open(test_path.string().c_str(), O_RDONLY|O_DIRECT|O_SYNC);
|
int f = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
if (-1 == f)
|
||||||
"opened, error: " << strerror(errno);
|
{
|
||||||
char * raw_array = (char*) memalign(
|
SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
|
||||||
512,
|
return -1;
|
||||||
number_of_elements*sizeof(unsigned)
|
}
|
||||||
);
|
char *raw_array = (char *)memalign(512, number_of_elements * sizeof(unsigned));
|
||||||
#endif
|
#endif
|
||||||
time1 = get_timestamp();
|
time1 = get_timestamp();
|
||||||
#ifdef __APPLE__
|
#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));
|
close(fileno(fd));
|
||||||
fd = fopen(test_path.string().c_str(), "r");
|
fd = fopen(test_path.string().c_str(), "r");
|
||||||
#endif
|
#endif
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
int ret = read(f, raw_array, number_of_elements*sizeof(unsigned));
|
int ret = read(f, raw_array, number_of_elements * sizeof(unsigned));
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
SimpleLogger().Write(logDEBUG) << "read " << ret
|
||||||
"read " << ret << " bytes, error: " << strerror(errno);
|
<< " bytes, error: " << strerror(errno);
|
||||||
close(f);
|
close(f);
|
||||||
f = open(test_path.string().c_str(), O_RDONLY|O_DIRECT|O_SYNC);
|
f = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
|
||||||
"opened, error: " << strerror(errno);
|
|
||||||
#endif
|
#endif
|
||||||
time2 = get_timestamp();
|
time2 = get_timestamp();
|
||||||
|
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
SimpleLogger().Write(logDEBUG) << "reading raw 1GB took " << (time2 - time1) * 1000
|
||||||
"reading raw 1GB took " << (time2-time1)*1000 << "ms";
|
<< "ms";
|
||||||
SimpleLogger().Write() << "raw read performance: " <<
|
SimpleLogger().Write() << "raw read performance: " << std::setprecision(5) << std::fixed
|
||||||
std::setprecision(5) << std::fixed <<
|
<< 1024 * 1024 / ((time2 - time1) * 1000) << "MB/sec";
|
||||||
1024*1024/((time2-time1)*1000) << "MB/sec";
|
|
||||||
|
|
||||||
std::vector<double> timing_results_raw_random;
|
std::vector<double> timing_results_raw_random;
|
||||||
SimpleLogger().Write(logDEBUG) << "running 1000 random I/Os of 4KB";
|
SimpleLogger().Write(logDEBUG) << "running 1000 random I/Os of 4KB";
|
||||||
@@ -217,60 +198,59 @@ int main (int argc, char * argv[]) {
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
lseek(f, 0, SEEK_SET);
|
lseek(f, 0, SEEK_SET);
|
||||||
#endif
|
#endif
|
||||||
//make 1000 random access, time each I/O seperately
|
// make 1000 random access, time each I/O seperately
|
||||||
unsigned number_of_blocks = (number_of_elements*sizeof(unsigned)-1)/4096;
|
unsigned number_of_blocks = (number_of_elements * sizeof(unsigned) - 1) / 4096;
|
||||||
for(unsigned i = 0; i < 1000; ++i) {
|
for (unsigned i = 0; i < 1000; ++i)
|
||||||
unsigned block_to_read = std::rand()%number_of_blocks;
|
{
|
||||||
off_t current_offset = block_to_read*4096;
|
unsigned block_to_read = std::rand() % number_of_blocks;
|
||||||
|
off_t current_offset = block_to_read * 4096;
|
||||||
time1 = get_timestamp();
|
time1 = get_timestamp();
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
int ret1 = fseek(fd, current_offset, SEEK_SET);
|
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
|
#endif
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
int ret1 = 0;
|
int ret1 = 0;
|
||||||
int ret2 = 0;
|
int ret2 = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
int ret1 = lseek(f, current_offset, SEEK_SET);
|
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
|
#endif
|
||||||
time2 = get_timestamp();
|
time2 = get_timestamp();
|
||||||
if( ((off_t)-1) == ret1) {
|
if (((off_t) - 1) == ret1)
|
||||||
SimpleLogger().Write(logWARNING)
|
{
|
||||||
<< "offset: " << current_offset;
|
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||||
SimpleLogger().Write(logWARNING)
|
SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
|
||||||
<< "seek error " << strerror(errno);
|
|
||||||
throw OSRMException("seek error");
|
throw OSRMException("seek error");
|
||||||
}
|
}
|
||||||
if(-1 == ret2) {
|
if (-1 == ret2)
|
||||||
SimpleLogger().Write(logWARNING)
|
{
|
||||||
<< "offset: " << current_offset;
|
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||||
SimpleLogger().Write(logWARNING)
|
SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
|
||||||
<< "read error " << strerror(errno);
|
|
||||||
throw OSRMException("read error");
|
throw OSRMException("read error");
|
||||||
}
|
}
|
||||||
timing_results_raw_random.push_back((time2-time1)*1000.);
|
timing_results_raw_random.push_back((time2 - time1) * 1000.);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do statistics
|
// Do statistics
|
||||||
SimpleLogger().Write(logDEBUG) << "running raw random I/O statistics";
|
SimpleLogger().Write(logDEBUG) << "running raw random I/O statistics";
|
||||||
std::ofstream random_csv("random.csv", std::ios::trunc);
|
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 << i << ", " << timing_results_raw_random[i] << std::endl;
|
||||||
}
|
}
|
||||||
random_csv.close();
|
random_csv.close();
|
||||||
RunStatistics(timing_results_raw_random, stats);
|
RunStatistics(timing_results_raw_random, stats);
|
||||||
|
|
||||||
SimpleLogger().Write() << "raw random I/O: " <<
|
SimpleLogger().Write() << "raw random I/O: " << std::setprecision(5) << std::fixed
|
||||||
std::setprecision(5) << std::fixed <<
|
<< "min: " << stats.min << "ms, "
|
||||||
"min: " << stats.min << "ms, " <<
|
<< "mean: " << stats.mean << "ms, "
|
||||||
"mean: " << stats.mean << "ms, " <<
|
<< "med: " << stats.med << "ms, "
|
||||||
"med: " << stats.med << "ms, " <<
|
<< "max: " << stats.max << "ms, "
|
||||||
"max: " << stats.max << "ms, " <<
|
<< "dev: " << stats.dev << "ms";
|
||||||
"dev: " << stats.dev << "ms";
|
|
||||||
|
|
||||||
std::vector<double> timing_results_raw_seq;
|
std::vector<double> timing_results_raw_seq;
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@@ -280,81 +260,80 @@ int main (int argc, char * argv[]) {
|
|||||||
lseek(f, 0, SEEK_SET);
|
lseek(f, 0, SEEK_SET);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//read every 100th block
|
// read every 100th block
|
||||||
for(
|
for (unsigned i = 0; i < 1000; ++i)
|
||||||
unsigned i = 0;
|
{
|
||||||
i < 1000;
|
off_t current_offset = i * 4096;
|
||||||
++i
|
|
||||||
) {
|
|
||||||
off_t current_offset = i*4096;
|
|
||||||
time1 = get_timestamp();
|
time1 = get_timestamp();
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
int ret1 = fseek(fd, current_offset, SEEK_SET);
|
int ret1 = fseek(fd, current_offset, SEEK_SET);
|
||||||
int ret2 = read(fileno(fd), (char*)&single_block, 4096);
|
int ret2 = read(fileno(fd), (char *)&single_block, 4096);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
int ret1 = 0;
|
int ret1 = 0;
|
||||||
int ret2 = 0;
|
int ret2 = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
int ret1 = lseek(f, current_offset, SEEK_SET);
|
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
|
#endif
|
||||||
time2 = get_timestamp();
|
time2 = get_timestamp();
|
||||||
if( ((off_t)-1) == ret1) {
|
if (((off_t) - 1) == ret1)
|
||||||
SimpleLogger().Write(logWARNING)
|
{
|
||||||
<< "offset: " << current_offset;
|
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||||
SimpleLogger().Write(logWARNING)
|
SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
|
||||||
<< "seek error " << strerror(errno);
|
|
||||||
throw OSRMException("seek error");
|
throw OSRMException("seek error");
|
||||||
}
|
}
|
||||||
if(-1 == ret2) {
|
if (-1 == ret2)
|
||||||
SimpleLogger().Write(logWARNING)
|
{
|
||||||
<< "offset: " << current_offset;
|
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||||
SimpleLogger().Write(logWARNING)
|
SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
|
||||||
<< "read error " << strerror(errno);
|
|
||||||
throw OSRMException("read error");
|
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);
|
fclose(fd);
|
||||||
// free(single_element);
|
// free(single_element);
|
||||||
free(raw_array);
|
free(raw_array);
|
||||||
// free(single_block);
|
// free(single_block);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
close(f);
|
close(f);
|
||||||
#endif
|
#endif
|
||||||
//Do statistics
|
// Do statistics
|
||||||
SimpleLogger().Write(logDEBUG) << "running sequential I/O 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);
|
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 << i << ", " << timing_results_raw_seq[i] << std::endl;
|
||||||
}
|
}
|
||||||
seq_csv.close();
|
seq_csv.close();
|
||||||
RunStatistics(timing_results_raw_seq, stats);
|
RunStatistics(timing_results_raw_seq, stats);
|
||||||
SimpleLogger().Write() << "raw sequential I/O: " <<
|
SimpleLogger().Write() << "raw sequential I/O: " << std::setprecision(5) << std::fixed
|
||||||
std::setprecision(5) << std::fixed <<
|
<< "min: " << stats.min << "ms, "
|
||||||
"min: " << stats.min << "ms, " <<
|
<< "mean: " << stats.mean << "ms, "
|
||||||
"mean: " << stats.mean << "ms, " <<
|
<< "med: " << stats.med << "ms, "
|
||||||
"med: " << stats.med << "ms, " <<
|
<< "max: " << stats.max << "ms, "
|
||||||
"max: " << stats.max << "ms, " <<
|
<< "dev: " << stats.dev << "ms";
|
||||||
"dev: " << stats.dev << "ms";
|
|
||||||
|
|
||||||
if( boost::filesystem::exists(test_path) ) {
|
if (boost::filesystem::exists(test_path))
|
||||||
|
{
|
||||||
boost::filesystem::remove(test_path);
|
boost::filesystem::remove(test_path);
|
||||||
SimpleLogger().Write(logDEBUG) << "removing temporary files";
|
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) << "caught exception: " << e.what();
|
||||||
SimpleLogger().Write(logWARNING) << "cleaning up, and exiting";
|
SimpleLogger().Write(logWARNING) << "cleaning up, and exiting";
|
||||||
if(boost::filesystem::exists(test_path)) {
|
if (boost::filesystem::exists(test_path))
|
||||||
|
{
|
||||||
boost::filesystem::remove(test_path);
|
boost::filesystem::remove(test_path);
|
||||||
SimpleLogger().Write(logWARNING) << "removing temporary files";
|
SimpleLogger().Write(logWARNING) << "removing temporary files";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,13 +33,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
LogPolicy::GetInstance().Unmute();
|
LogPolicy::GetInstance().Unmute();
|
||||||
SimpleLogger().Write() <<
|
try
|
||||||
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
{
|
||||||
"compiled at " << __DATE__ << ", " __TIME__;
|
SimpleLogger().Write() <<
|
||||||
SimpleLogger().Write() << "Releasing all locks";
|
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
||||||
SharedBarriers barrier;
|
"compiled at " << __DATE__ << ", " __TIME__;
|
||||||
barrier.pending_update_mutex.unlock();
|
SimpleLogger().Write() << "Releasing all locks";
|
||||||
barrier.query_mutex.unlock();
|
SharedBarriers barrier;
|
||||||
barrier.update_mutex.unlock();
|
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;
|
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"]),
|
boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
|
||||||
".edges file"
|
".edges file"
|
||||||
)
|
)
|
||||||
// (
|
(
|
||||||
// "geometry",
|
"geometry",
|
||||||
// boost::program_options::value<boost::filesystem::path>(&paths["geometries"]),
|
boost::program_options::value<boost::filesystem::path>(&paths["geometry"]),
|
||||||
// ".geometry file"
|
".geometry file"
|
||||||
// )
|
)
|
||||||
(
|
(
|
||||||
"ramindex",
|
"ramindex",
|
||||||
boost::program_options::value<boost::filesystem::path>(&paths["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);
|
boost::program_options::notify(option_variables);
|
||||||
|
|
||||||
const bool parameter_present =
|
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("nodesdata") != paths.end() && !paths.find("nodesdata")->second.string().empty()) ||
|
||||||
(paths.find("edgesdata") != paths.end() && !paths.find("edgesdata")->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("geometry") != paths.end() && !paths.find("geometry" )->second.string().empty()) ||
|
||||||
(paths.find("ramindex") != paths.end() && !paths.find("ramindex")->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("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)
|
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->second = base_string + ".edges";
|
||||||
}
|
}
|
||||||
|
|
||||||
// path_iterator = paths.find("geometries");
|
path_iterator = paths.find("geometry");
|
||||||
// if (path_iterator != paths.end())
|
if (path_iterator != paths.end())
|
||||||
// {
|
{
|
||||||
// path_iterator->second = base_string + ".geometry";
|
path_iterator->second = base_string + ".geometry";
|
||||||
// }
|
}
|
||||||
|
|
||||||
path_iterator = paths.find("ramindex");
|
path_iterator = paths.find("ramindex");
|
||||||
if (path_iterator != paths.end())
|
if (path_iterator != paths.end())
|
||||||
@@ -296,12 +296,12 @@ inline bool GenerateDataStoreOptions(const int argc, const char * argv[], Server
|
|||||||
}
|
}
|
||||||
AssertPathExists(path_iterator->second);
|
AssertPathExists(path_iterator->second);
|
||||||
|
|
||||||
// path_iterator = paths.find("geometries");
|
path_iterator = paths.find("geometry");
|
||||||
// if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||||
// {
|
{
|
||||||
// path_iterator->second = base_string + ".geometry";
|
throw OSRMException(".geometry file must be specified");
|
||||||
// }
|
}
|
||||||
// AssertPathExists(path_iterator->second);
|
AssertPathExists(path_iterator->second);
|
||||||
|
|
||||||
path_iterator = paths.find("ramindex");
|
path_iterator = paths.find("ramindex");
|
||||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
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 "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
@@ -135,7 +136,7 @@ NodeID readBinaryOSRMGraphFromStream(
|
|||||||
short type;
|
short type;
|
||||||
NodeID nameID;
|
NodeID nameID;
|
||||||
int length;
|
int length;
|
||||||
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow;
|
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, is_split;
|
||||||
|
|
||||||
for (EdgeID i=0; i<m; ++i) {
|
for (EdgeID i=0; i<m; ++i) {
|
||||||
input_stream.read((char*)&source, sizeof(unsigned));
|
input_stream.read((char*)&source, sizeof(unsigned));
|
||||||
@@ -149,6 +150,7 @@ NodeID readBinaryOSRMGraphFromStream(
|
|||||||
input_stream.read((char*)&ignoreInGrid, sizeof(bool));
|
input_stream.read((char*)&ignoreInGrid, sizeof(bool));
|
||||||
input_stream.read((char*)&isAccessRestricted, sizeof(bool));
|
input_stream.read((char*)&isAccessRestricted, sizeof(bool));
|
||||||
input_stream.read((char*)&isContraFlow, 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(length > 0, "loaded null length edge" );
|
||||||
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
|
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
|
||||||
@@ -189,7 +191,7 @@ NodeID readBinaryOSRMGraphFromStream(
|
|||||||
std::swap(forward, backward);
|
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);
|
edge_list.push_back(inputEdge);
|
||||||
}
|
}
|
||||||
std::sort(edge_list.begin(), edge_list.end());
|
std::sort(edge_list.begin(), edge_list.end());
|
||||||
@@ -444,7 +446,10 @@ unsigned readHSGRFromStream(
|
|||||||
hsgr_input_stream.read( (char*) &number_of_nodes, sizeof(unsigned) );
|
hsgr_input_stream.read( (char*) &number_of_nodes, sizeof(unsigned) );
|
||||||
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
|
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
|
||||||
hsgr_input_stream.read( (char*) &number_of_edges, sizeof(unsigned) );
|
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);
|
node_list.resize(number_of_nodes + 1);
|
||||||
hsgr_input_stream.read(
|
hsgr_input_stream.read(
|
||||||
(char*) &(node_list[0]),
|
(char*) &(node_list[0]),
|
||||||
@@ -457,6 +462,7 @@ unsigned readHSGRFromStream(
|
|||||||
number_of_edges*sizeof(EdgeT)
|
number_of_edges*sizeof(EdgeT)
|
||||||
);
|
);
|
||||||
hsgr_input_stream.close();
|
hsgr_input_stream.close();
|
||||||
|
|
||||||
return number_of_nodes;
|
return number_of_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
class IniFile {
|
class IniFile {
|
||||||
public:
|
public:
|
||||||
IniFile(const char * config_filename);
|
explicit IniFile(const char * config_filename);
|
||||||
|
|
||||||
std::string GetParameter(const std::string & key);
|
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 {
|
class OSRMException: public std::exception {
|
||||||
public:
|
public:
|
||||||
OSRMException(const char * message) : message(message) {}
|
explicit OSRMException(const char * message) : message(message) {}
|
||||||
OSRMException(const std::string & message) : message(message) {}
|
explicit OSRMException(const std::string & message) : message(message) {}
|
||||||
virtual ~OSRMException() throw() {}
|
virtual ~OSRMException() throw() {}
|
||||||
private:
|
private:
|
||||||
virtual const char* what() const throw() {
|
virtual const char* what() const throw() {
|
||||||
|
|||||||
@@ -110,6 +110,10 @@ inline unsigned GenerateServerProgramOptions(
|
|||||||
"edgesdata",
|
"edgesdata",
|
||||||
boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
|
boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
|
||||||
".edges file")
|
".edges file")
|
||||||
|
(
|
||||||
|
"geometry",
|
||||||
|
boost::program_options::value<boost::filesystem::path>(&paths["geometries"]),
|
||||||
|
".geometry file")
|
||||||
(
|
(
|
||||||
"ramindex",
|
"ramindex",
|
||||||
boost::program_options::value<boost::filesystem::path>(&paths["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");
|
path_iterator = paths.find("ramindex");
|
||||||
if(
|
if(
|
||||||
path_iterator != paths.end() &&
|
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/noncopyable.hpp>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
enum LogLevel { logINFO, logWARNING, logDEBUG };
|
enum LogLevel { logINFO, logWARNING, logDEBUG };
|
||||||
static boost::mutex logger_mutex;
|
static boost::mutex logger_mutex;
|
||||||
const char COL_RESET[] = "\x1b[0m";
|
const char COL_RESET[] = "\x1b[0m";
|
||||||
const char RED[] = "\x1b[31m";
|
const char RED[] = "\x1b[31m";
|
||||||
const char GREEN[] = "\x1b[32m";
|
const char GREEN[] = "\x1b[32m";
|
||||||
@@ -70,16 +72,20 @@ private:
|
|||||||
bool m_is_mute;
|
bool m_is_mute;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SimpleLogger {
|
class SimpleLogger
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
SimpleLogger() : level(logINFO) { }
|
SimpleLogger() : level(logINFO) { }
|
||||||
|
|
||||||
std::ostringstream& Write(LogLevel l = logINFO) {
|
std::ostringstream& Write(LogLevel l = logINFO)
|
||||||
try {
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
boost::mutex::scoped_lock lock(logger_mutex);
|
boost::mutex::scoped_lock lock(logger_mutex);
|
||||||
level = l;
|
level = l;
|
||||||
os << "[";
|
os << "[";
|
||||||
switch(level) {
|
switch(level)
|
||||||
|
{
|
||||||
case logINFO:
|
case logINFO:
|
||||||
os << "info";
|
os << "info";
|
||||||
break;
|
break;
|
||||||
@@ -96,22 +102,26 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
os << "] ";
|
os << "] ";
|
||||||
} catch (...) { }
|
}
|
||||||
|
catch (...) { }
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~SimpleLogger() {
|
virtual ~SimpleLogger() {
|
||||||
if(!LogPolicy::GetInstance().IsMute()) {
|
if(!LogPolicy::GetInstance().IsMute())
|
||||||
switch(level) {
|
{
|
||||||
|
const bool is_terminal = isatty(fileno(stdout));
|
||||||
|
switch(level)
|
||||||
|
{
|
||||||
case logINFO:
|
case logINFO:
|
||||||
std::cout << os.str() << COL_RESET << std::endl;
|
std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
|
||||||
break;
|
break;
|
||||||
case logWARNING:
|
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;
|
break;
|
||||||
case logDEBUG:
|
case logDEBUG:
|
||||||
#ifndef NDEBUG
|
#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
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -126,6 +126,40 @@ static inline uint64_t stringToInt64(const std::string& input) {
|
|||||||
return value;
|
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){
|
static inline void doubleToString(const double value, std::string & output){
|
||||||
output.clear();
|
output.clear();
|
||||||
|
|||||||
+86
-25
@@ -44,22 +44,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/integer.hpp>
|
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
#include <boost/iostreams/seek.hpp>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
int main( const int argc, const char * argv[] ) {
|
int main( const int argc, const char * argv[] )
|
||||||
|
{
|
||||||
LogPolicy::GetInstance().Unmute();
|
LogPolicy::GetInstance().Unmute();
|
||||||
SharedBarriers barrier;
|
SharedBarriers barrier;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if( -1 == mlockall(MCL_CURRENT | MCL_FUTURE) ) {
|
const bool lock_flags = MCL_CURRENT | MCL_FUTURE;
|
||||||
SimpleLogger().Write(logWARNING) <<
|
if (-1 == mlockall(lock_flags))
|
||||||
"Process " << argv[0] << " could not request RAM lock";
|
{
|
||||||
}
|
SimpleLogger().Write(logWARNING) << "Process " << argv[0] << " could not request RAM lock";
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -89,22 +92,25 @@ int main( const int argc, const char * argv[] ) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if( server_paths.find("hsgrdata") == server_paths.end() ) {
|
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() ) {
|
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() ) {
|
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() ) {
|
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() ) {
|
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() ) {
|
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");
|
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(server_paths.end() != paths_iterator);
|
||||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
const boost::filesystem::path & names_data_path = paths_iterator->second;
|
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
|
// get the shared memory segment to use
|
||||||
bool use_first_segment = SharedMemory::RegionExists( LAYOUT_2 );
|
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';
|
shared_layout_ptr->ram_index_file_name[end_of_string_index] = '\0';
|
||||||
|
|
||||||
// collect number of elements to store in shared memory object
|
// collect number of elements to store in shared memory object
|
||||||
SimpleLogger().Write(logDEBUG) << "Collecting files sizes";
|
|
||||||
SimpleLogger().Write() << "load names from: " << names_data_path;
|
SimpleLogger().Write() << "load names from: " << names_data_path;
|
||||||
// number of entries in name index
|
// number of entries in name index
|
||||||
boost::filesystem::ifstream name_stream(
|
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->via_node_list_size = number_of_original_edges;
|
||||||
shared_layout_ptr->name_id_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->turn_instruction_list_size = number_of_original_edges;
|
||||||
|
shared_layout_ptr->geometries_indicators = number_of_original_edges;
|
||||||
|
|
||||||
boost::filesystem::ifstream hsgr_input_stream(
|
boost::filesystem::ifstream hsgr_input_stream(
|
||||||
hsgr_path,
|
hsgr_path,
|
||||||
@@ -200,13 +209,15 @@ int main( const int argc, const char * argv[] ) {
|
|||||||
|
|
||||||
UUID uuid_loaded, uuid_orig;
|
UUID uuid_loaded, uuid_orig;
|
||||||
hsgr_input_stream.read((char *)&uuid_loaded, sizeof(UUID));
|
hsgr_input_stream.read((char *)&uuid_loaded, sizeof(UUID));
|
||||||
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
|
if (uuid_loaded.TestGraphUtil(uuid_orig))
|
||||||
SimpleLogger().Write(logWARNING) <<
|
{
|
||||||
".hsgr was prepared with different build. "
|
|
||||||
"Reprocess to get rid of this warning.";
|
|
||||||
} else {
|
|
||||||
SimpleLogger().Write(logDEBUG) << "UUID checked out ok";
|
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
|
// load checksum
|
||||||
unsigned checksum = 0;
|
unsigned checksum = 0;
|
||||||
@@ -274,8 +285,21 @@ int main( const int argc, const char * argv[] ) {
|
|||||||
shared_layout_ptr->coordinate_list_size = coordinate_list_size;
|
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";
|
SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout() << " bytes";
|
||||||
SharedMemory * shared_memory = SharedMemoryFactory::Get(
|
SharedMemory * shared_memory = SharedMemoryFactory::Get(
|
||||||
DATA,
|
DATA,
|
||||||
@@ -285,11 +309,9 @@ int main( const int argc, const char * argv[] ) {
|
|||||||
|
|
||||||
// read actual data into shared memory object //
|
// read actual data into shared memory object //
|
||||||
// Loading street names
|
// Loading street names
|
||||||
// SimpleLogger().Write() << "Loading names index and chars from: " << names_data_path.string();
|
|
||||||
unsigned * name_index_ptr = (unsigned*)(
|
unsigned * name_index_ptr = (unsigned*)(
|
||||||
shared_memory_ptr + shared_layout_ptr->GetNameIndexOffset()
|
shared_memory_ptr + shared_layout_ptr->GetNameIndexOffset()
|
||||||
);
|
);
|
||||||
// SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_index_list_size*sizeof(unsigned);
|
|
||||||
|
|
||||||
name_stream.read(
|
name_stream.read(
|
||||||
(char*)name_index_ptr,
|
(char*)name_index_ptr,
|
||||||
@@ -316,9 +338,12 @@ int main( const int argc, const char * argv[] ) {
|
|||||||
shared_memory_ptr + shared_layout_ptr->GetTurnInstructionListOffset()
|
shared_memory_ptr + shared_layout_ptr->GetTurnInstructionListOffset()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
unsigned * geometries_indicator_ptr = (unsigned *)(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetGeometriesIndicatorOffset()
|
||||||
|
);
|
||||||
|
|
||||||
OriginalEdgeData current_edge_data;
|
OriginalEdgeData current_edge_data;
|
||||||
for(unsigned i = 0; i < number_of_original_edges; ++i) {
|
for(unsigned i = 0; i < number_of_original_edges; ++i) {
|
||||||
// SimpleLogger().Write() << i << "/" << number_of_edges;
|
|
||||||
edges_input_stream.read(
|
edges_input_stream.read(
|
||||||
(char*)&(current_edge_data),
|
(char*)&(current_edge_data),
|
||||||
sizeof(OriginalEdgeData)
|
sizeof(OriginalEdgeData)
|
||||||
@@ -326,9 +351,43 @@ int main( const int argc, const char * argv[] ) {
|
|||||||
via_node_ptr[i] = current_edge_data.via_node;
|
via_node_ptr[i] = current_edge_data.via_node;
|
||||||
name_id_ptr[i] = current_edge_data.name_id;
|
name_id_ptr[i] = current_edge_data.name_id;
|
||||||
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
|
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();
|
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
|
// Loading list of coordinates
|
||||||
FixedPointCoordinate * coordinates_ptr = (FixedPointCoordinate *)(
|
FixedPointCoordinate * coordinates_ptr = (FixedPointCoordinate *)(
|
||||||
shared_memory_ptr + shared_layout_ptr->GetCoordinateListOffset()
|
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
|
// load the edges of the search graph
|
||||||
QueryGraph::_StrEdge * graph_edge_list_ptr = (QueryGraph::_StrEdge *)(
|
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(
|
hsgr_input_stream.read(
|
||||||
(char*) graph_edge_list_ptr,
|
(char*) graph_edge_list_ptr,
|
||||||
@@ -421,6 +480,8 @@ int main( const int argc, const char * argv[] ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SimpleLogger().Write() << "all data loaded";
|
SimpleLogger().Write() << "all data loaded";
|
||||||
|
|
||||||
|
shared_layout_ptr->PrintInformation();
|
||||||
} catch(const std::exception & e) {
|
} catch(const std::exception & e) {
|
||||||
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
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 <cstdlib>
|
||||||
|
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -99,12 +101,14 @@ int main (int argc, char *argv[]) {
|
|||||||
boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
|
boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
|
||||||
options(cmdline_options).positional(positional_options).run(), option_variables);
|
options(cmdline_options).positional(positional_options).run(), option_variables);
|
||||||
|
|
||||||
if(option_variables.count("version")) {
|
if(option_variables.count("version"))
|
||||||
|
{
|
||||||
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(option_variables.count("help")) {
|
if(option_variables.count("help"))
|
||||||
|
{
|
||||||
SimpleLogger().Write() << visible_options;
|
SimpleLogger().Write() << visible_options;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -112,24 +116,38 @@ int main (int argc, char *argv[]) {
|
|||||||
boost::program_options::notify(option_variables);
|
boost::program_options::notify(option_variables);
|
||||||
|
|
||||||
// parse config file
|
// parse config file
|
||||||
if(boost::filesystem::is_regular_file(config_file_path)) {
|
if(boost::filesystem::is_regular_file(config_file_path))
|
||||||
SimpleLogger().Write() << "Reading options from: " << config_file_path.c_str();
|
{
|
||||||
|
SimpleLogger().Write() << "Reading options from: " << config_file_path.string();
|
||||||
std::string config_str;
|
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 );
|
std::stringstream config_stream( config_str );
|
||||||
boost::program_options::store(parse_config_file(config_stream, config_file_options), option_variables);
|
boost::program_options::store(parse_config_file(config_stream, config_file_options), option_variables);
|
||||||
boost::program_options::notify(option_variables);
|
boost::program_options::notify(option_variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!option_variables.count("input")) {
|
if(!option_variables.count("input"))
|
||||||
SimpleLogger().Write(logWARNING) << "No input file specified";
|
{
|
||||||
SimpleLogger().Write() << visible_options;
|
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";
|
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();
|
SimpleLogger().Write() << "Input file: " << input_path.filename().string();
|
||||||
@@ -139,51 +157,65 @@ int main (int argc, char *argv[]) {
|
|||||||
/*** Setup Scripting Environment ***/
|
/*** Setup Scripting Environment ***/
|
||||||
ScriptingEnvironment scriptingEnvironment(profile_path.c_str());
|
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);
|
bool file_has_pbf_format(false);
|
||||||
std::string output_file_name(input_path.c_str());
|
std::string output_file_name = input_path.string();
|
||||||
std::string restrictionsFileName(input_path.c_str());
|
std::string restrictionsFileName = input_path.string();
|
||||||
std::string::size_type pos = output_file_name.find(".osm.bz2");
|
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");
|
pos = output_file_name.find(".osm.pbf");
|
||||||
if(pos!=std::string::npos) {
|
if (pos!=std::string::npos)
|
||||||
|
{
|
||||||
file_has_pbf_format = true;
|
file_has_pbf_format = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pos==std::string::npos) {
|
if (pos==std::string::npos)
|
||||||
|
{
|
||||||
pos = output_file_name.find(".pbf");
|
pos = output_file_name.find(".pbf");
|
||||||
if(pos!=std::string::npos) {
|
if (pos!=std::string::npos)
|
||||||
|
{
|
||||||
file_has_pbf_format = true;
|
file_has_pbf_format = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pos!=std::string::npos) {
|
if (pos == std::string::npos)
|
||||||
output_file_name.replace(pos, 8, ".osrm");
|
{
|
||||||
restrictionsFileName.replace(pos, 8, ".osrm.restrictions");
|
pos = output_file_name.find(".osm");
|
||||||
} else {
|
if (pos == std::string::npos)
|
||||||
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 {
|
|
||||||
output_file_name.append(".osrm");
|
output_file_name.append(".osrm");
|
||||||
restrictionsFileName.append(".osrm.restrictions");
|
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;
|
ExtractionContainers externalMemory;
|
||||||
|
|
||||||
stringMap[""] = 0;
|
stringMap[""] = 0;
|
||||||
extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap);
|
extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap);
|
||||||
BaseParser* parser;
|
BaseParser* parser;
|
||||||
if(file_has_pbf_format) {
|
if(file_has_pbf_format)
|
||||||
|
{
|
||||||
parser = new PBFParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
|
parser = new PBFParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
parser = new XMLParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
|
parser = new XMLParser(input_path.c_str(), extractCallBacks, scriptingEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!parser->ReadHeader()) {
|
if(!parser->ReadHeader())
|
||||||
|
{
|
||||||
throw OSRMException("Parser not initialized!");
|
throw OSRMException("Parser not initialized!");
|
||||||
}
|
}
|
||||||
SimpleLogger().Write() << "Parsing in progress..";
|
SimpleLogger().Write() << "Parsing in progress..";
|
||||||
@@ -193,9 +225,10 @@ int main (int argc, char *argv[]) {
|
|||||||
(get_timestamp() - parsing_start_time) <<
|
(get_timestamp() - parsing_start_time) <<
|
||||||
" seconds";
|
" seconds";
|
||||||
|
|
||||||
if( externalMemory.all_edges_list.empty() ) {
|
if (externalMemory.all_edges_list.empty())
|
||||||
|
{
|
||||||
SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
|
SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
externalMemory.PrepareData(output_file_name, restrictionsFileName);
|
externalMemory.PrepareData(output_file_name, restrictionsFileName);
|
||||||
@@ -203,22 +236,19 @@ int main (int argc, char *argv[]) {
|
|||||||
delete parser;
|
delete parser;
|
||||||
delete extractCallBacks;
|
delete extractCallBacks;
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "extraction finished after " << get_timestamp() - startup_time << "s";
|
||||||
"extraction finished after " << get_timestamp() - startup_time <<
|
SimpleLogger().Write() << "To prepare the data for routing, run: " << "./osrm-prepare " << output_file_name << std::endl;
|
||||||
"s";
|
|
||||||
|
|
||||||
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";
|
SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
|
||||||
return -1;
|
return 1;
|
||||||
} catch(boost::program_options::error& e) {
|
}
|
||||||
SimpleLogger().Write(logWARNING) << e.what();
|
catch(std::exception & e)
|
||||||
return -1;
|
{
|
||||||
} catch(std::exception & e) {
|
SimpleLogger().Write(logWARNING) << "Exception occured: " << e.what();
|
||||||
SimpleLogger().Write(logWARNING) << "Unhandled exception: " << e.what();
|
return 1;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
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 |
|
| bc | trunk | 60 |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | speed |
|
| from | to | route | speed |
|
||||||
| a | b | ab | 85 km/h |
|
| a | b | ab | 85 km/h |
|
||||||
| b | c | bc | 40 km/h |
|
| b | c | bc | 40 km/h +- 1 |
|
||||||
|
|
||||||
Scenario: Car - Do not ignore maxspeed when higher than way speed
|
Scenario: Car - Do not ignore maxspeed when higher than way speed
|
||||||
Given the node map
|
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 |
|
| bc | residential | 90 |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | speed |
|
| from | to | route | speed |
|
||||||
| a | b | ab | 25 km/h |
|
| a | b | ab | 25 km/h |
|
||||||
| b | c | bc | 60 km/h |
|
| b | c | bc | 60 km/h +- 1 |
|
||||||
|
|
||||||
Scenario: Car - Forward/backward maxspeed
|
Scenario: Car - Forward/backward maxspeed
|
||||||
Given a grid size of 100 meters
|
Given a grid size of 100 meters
|
||||||
|
|
||||||
Then routability should be
|
Then routability should be
|
||||||
| highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw |
|
| highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw |
|
||||||
| primary | | | | 65 km/h | 65 km/h |
|
| primary | | | | 65 km/h | 65 km/h |
|
||||||
| primary | 60 | | | 40 km/h | 40 km/h |
|
| primary | 60 | | | 40 km/h | 40 km/h |
|
||||||
| primary | | 60 | | 40 km/h | 65 km/h |
|
| primary | | 60 | | 40 km/h | 65 km/h |
|
||||||
| primary | | | 60 | 65 km/h | 40 km/h |
|
| primary | | | 60 | 65 km/h | 40 km/h |
|
||||||
| primary | 15 | 60 | | 40 km/h | 10 km/h |
|
| primary | 15 | 60 | | 40 km/h | 10 km/h +- 1 |
|
||||||
| primary | 15 | | 60 | 10 km/h | 40 km/h |
|
| primary | 15 | | 60 | 10 km/h +- 1| 40 km/h |
|
||||||
| primary | 15 | 30 | 60 | 20 km/h | 40 km/h |
|
| primary | 15 | 30 | 60 | 20 km/h | 40 km/h |
|
||||||
|
|
||||||
Scenario: Car - Maxspeed should not allow routing on unroutable ways
|
Scenario: Car - Maxspeed should not allow routing on unroutable ways
|
||||||
Then routability should be
|
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 | | | | | | |
|
||||||
| runway | | | 100 | | | |
|
| runway | | | 100 | | | |
|
||||||
| runway | | | | 100 | | |
|
| runway | | | | 100 | | |
|
||||||
| runway | | | | | 100 | |
|
| runway | | | | | 100 | |
|
||||||
|
|||||||
+17
-17
@@ -1,24 +1,24 @@
|
|||||||
@routing @car @speed
|
@routing @car @speed
|
||||||
Feature: Car - speeds
|
Feature: Car - speeds
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "car"
|
Given the profile "car"
|
||||||
And a grid size of 1000 meters
|
And a grid size of 1000 meters
|
||||||
|
|
||||||
Scenario: Car - speed of various way types
|
Scenario: Car - speed of various way types
|
||||||
Then routability should be
|
Then routability should be
|
||||||
| highway | oneway | bothw |
|
| highway | oneway | bothw |
|
||||||
| motorway | no | 90 km/h |
|
| motorway | no | 90 km/h |
|
||||||
| motorway_link | no | 75 km/h |
|
| motorway_link | no | 75 km/h |
|
||||||
| trunk | no | 85 km/h |
|
| trunk | no | 85 km/h +- 1 |
|
||||||
| trunk_link | no | 70 km/h |
|
| trunk_link | no | 70 km/h +- 1 |
|
||||||
| primary | no | 65 km/h |
|
| primary | no | 65 km/h +- 1 |
|
||||||
| primary_link | no | 60 km/h |
|
| primary_link | no | 60 km/h |
|
||||||
| secondary | no | 55 km/h |
|
| secondary | no | 55 km/h +- 1 |
|
||||||
| secondary_link | no | 50 km/h |
|
| secondary_link | no | 50 km/h |
|
||||||
| tertiary | no | 40 km/h |
|
| tertiary | no | 40 km/h |
|
||||||
| tertiary_link | no | 30 km/h |
|
| tertiary_link | no | 30 km/h |
|
||||||
| unclassified | no | 25 km/h |
|
| unclassified | no | 25 km/h |
|
||||||
| residential | no | 25 km/h |
|
| residential | no | 25 km/h |
|
||||||
| living_street | no | 10 km/h |
|
| living_street | no | 10 km/h |
|
||||||
| service | no | 15 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
|
@routed @options @files
|
||||||
Feature: Command line 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.
|
# 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
|
# For testing program options, the --trial option is used, which causes osrm-routed to quit
|
||||||
# immediately after initialization. This makes testing easier and faster.
|
# immediately after initialization. This makes testing easier and faster.
|
||||||
@@ -14,9 +14,9 @@ Feature: Command line options: files
|
|||||||
And the ways
|
And the ways
|
||||||
| nodes |
|
| nodes |
|
||||||
| ab |
|
| 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"
|
When I run "osrm-routed {base}.osrm --trial"
|
||||||
Then stdout should contain /^\[info\] starting up engines/
|
Then stdout should contain /^\[info\] starting up engines/
|
||||||
And stdout should contain /\d{1,2}\.\d{1,2}\.\d{1,2}/
|
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\] loaded plugin: viaroute/
|
||||||
And stdout should contain /^\[info\] trial run/
|
And stdout should contain /^\[info\] trial run/
|
||||||
And stdout should contain /^\[info\] shutdown completed/
|
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
|
@routed @options @help
|
||||||
Feature: Command line options: help
|
Feature: osrm-routed command line options: help
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
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"
|
When I run "osrm-routed"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain "osrm-routed <base.osrm> [<options>]:"
|
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 "--port"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--sharedmemory"
|
And stdout should contain "--sharedmemory"
|
||||||
|
And stdout should contain 22 lines
|
||||||
And it should exit with code 0
|
And it should exit with code 0
|
||||||
|
|
||||||
Scenario: Help, short
|
Scenario: osrm-routed - Help, short
|
||||||
When I run "osrm-routed -h"
|
When I run "osrm-routed -h"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain "osrm-routed <base.osrm> [<options>]:"
|
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 "--port"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--sharedmemory"
|
And stdout should contain "--sharedmemory"
|
||||||
|
And stdout should contain 22 lines
|
||||||
And it should exit with code 0
|
And it should exit with code 0
|
||||||
|
|
||||||
Scenario: Help, long
|
Scenario: osrm-routed - Help, long
|
||||||
When I run "osrm-routed --help"
|
When I run "osrm-routed --help"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain "osrm-routed <base.osrm> [<options>]:"
|
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 "--port"
|
||||||
And stdout should contain "--threads"
|
And stdout should contain "--threads"
|
||||||
And stdout should contain "--sharedmemory"
|
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
|
@routed @options @invalid
|
||||||
Feature: Command line options: invalid options
|
Feature: osrm-routed command line options: invalid options
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: Non-existing option
|
Scenario: osrm-routed - Non-existing option
|
||||||
When I run "osrm-routed --fly-me-to-the-moon"
|
When I run "osrm-routed --fly-me-to-the-moon"
|
||||||
Then stdout should be empty
|
Then stdout should be empty
|
||||||
And stderr should contain "exception"
|
And stderr should contain "exception"
|
||||||
And stderr should contain "fly-me-to-the-moon"
|
And stderr should contain "fly-me-to-the-moon"
|
||||||
And it should exit with code 1
|
And it should exit with code 1
|
||||||
|
|
||||||
Scenario: Missing file
|
Scenario: osrm-routed - Missing file
|
||||||
When I run "osrm-routed over-the-rainbow.osrm"
|
When I run "osrm-routed over-the-rainbow.osrm"
|
||||||
Then stdout should contain "over-the-rainbow.osrm"
|
Then stdout should contain "over-the-rainbow.osrm"
|
||||||
And stderr should contain "exception"
|
And stderr should contain "exception"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
@routing @options
|
@routed @options @version
|
||||||
Feature: Command line options: version
|
Feature: osrm-routed command line options: version
|
||||||
# the regex will match these two formats:
|
# the regex will match these two formats:
|
||||||
# v0.3.7.0 # this is the normal format when you build from a git clone
|
# 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)
|
# -128-NOTFOUND # if you build from a shallow clone (used on Travis)
|
||||||
@@ -7,14 +7,14 @@ Feature: Command line options: version
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: Version, short
|
Scenario: osrm-routed - Version, short
|
||||||
When I run "osrm-routed --v"
|
When I run "osrm-routed --v"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
And stdout should contain 1 line
|
||||||
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
And stdout should contain /(v\d{1,2}\.\d{1,2}\.\d{1,2}|\w*-\d+-\w+)/
|
||||||
And it should exit with code 0
|
And it should exit with code 0
|
||||||
|
|
||||||
Scenario: Version, long
|
Scenario: osrm-routed - Version, long
|
||||||
When I run "osrm-routed --version"
|
When I run "osrm-routed --version"
|
||||||
Then stderr should be empty
|
Then stderr should be empty
|
||||||
And stdout should contain 1 line
|
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'
|
raise "*** Input file must in .osm format" unless File.extname(file)=='.osm'
|
||||||
@osm_str = File.read file
|
@osm_str = File.read file
|
||||||
end
|
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|
|
When(/^I run "osrm\-routed\s?(.*?)"$/) do |options|
|
||||||
Dir.chdir TEST_FOLDER do
|
begin
|
||||||
if options.include? '{base}'
|
Timeout.timeout(1) { run_bin 'osrm-routed', options }
|
||||||
# expand {base} to base path of preprocessed data file
|
rescue Timeout::Error
|
||||||
raise "*** Cannot expand {base} without a preprocessed file." unless @osm_file
|
raise "*** osrm-routed didn't quit. Maybe the --trial option wasn't used?"
|
||||||
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
|
|
||||||
end
|
end
|
||||||
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|
|
Then /^it should exit with code (\d+)$/ do |code|
|
||||||
@exit_code.should == code.to_i
|
@exit_code.should == code.to_i
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -29,16 +29,8 @@ Then /^response should be a well-formed route$/ do
|
|||||||
@json['via_indices'].class.should == Array
|
@json['via_indices'].class.should == Array
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I preprocess data$/ do
|
|
||||||
begin
|
|
||||||
reprocess
|
|
||||||
rescue OSRMError => e
|
|
||||||
@process_error = e
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Then /^"([^"]*)" should return code (\d+)$/ do |binary, code|
|
Then /^"([^"]*)" should return code (\d+)$/ do |binary, code|
|
||||||
@process_error.is_a?(OSRMError).should == true
|
@process_error.is_a?(OSRMError).should == true
|
||||||
@process_error.process.should == binary
|
@process_error.process.should == binary
|
||||||
@process_error.code.to_i.should == code.to_i
|
@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