Merge pull request #992 from DennisOSRM/feature/remove_geometry

Feature/remove geometry
This commit is contained in:
Dennis Luxen 2014-04-28 11:34:49 +02:00
commit b77dd6699d
66 changed files with 3012 additions and 1664 deletions

View File

@ -81,7 +81,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug)
message(STATUS "Configuring OSRM in debug mode")
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
message(STATUS "adding profiling flags")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
endif()
endif()
@ -92,7 +92,7 @@ endif()
# Configuring compilers
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# using Clang
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
message(STATUS "OpenMP parallelization not available using clang++")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC

View File

@ -126,7 +126,6 @@ public:
newEdge.source = diter->source();
newEdge.target = diter->target();
newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
#ifndef NDEBUG
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
@ -737,6 +736,7 @@ private:
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
return false;
}
// TODO: C++11 copy_if with lambda
neighbours.push_back( target );
}

View File

@ -33,13 +33,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
//TODO: CompressionWorker
//TODO: EdgeBasedEdgeGenerator
// template<class Work>
// inline static void TraverseGraph(NodeBasedDynamicGraph & graph, Work & work) {
// }
#include <fstream>
#include <iomanip>
#include <numeric>
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
int number_of_nodes,
@ -47,13 +43,15 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
std::vector<NodeID> & barrier_node_list,
std::vector<NodeID> & traffic_light_node_list,
std::vector<TurnRestriction> & input_restrictions_list,
std::vector<NodeInfo> & node_info_list,
SpeedProfileProperties speed_profile
std::vector<NodeInfo> & m_node_info_list,
SpeedProfileProperties & speed_profile
) : speed_profile(speed_profile),
m_turn_restrictions_count(0),
m_node_info_list(node_info_list)
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
m_node_info_list(m_node_info_list),
max_id(0)
{
BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) {
BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) {
std::pair<NodeID, NodeID> restriction_source =
std::make_pair(restriction.fromNode, restriction.viaNode);
unsigned index;
@ -80,7 +78,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
);
}
m_barrier_nodes.insert(
m_barrier_nodes.insert(
barrier_node_list.begin(),
barrier_node_list.end()
);
@ -90,10 +88,15 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
traffic_light_node_list.end()
);
DeallocatingVector< NodeBasedEdge > edges_list;
std::sort( input_edge_list.begin(), input_edge_list.end() );
//TODO: remove duplicate edges
DeallocatingVector<NodeBasedEdge> edges_list;
NodeBasedEdge edge;
BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) {
if(!import_edge.isForward()) {
if( !import_edge.isForward() ) {
edge.source = import_edge.target();
edge.target = import_edge.source();
edge.data.backward = import_edge.isForward();
@ -104,33 +107,101 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
edge.data.forward = import_edge.isForward();
edge.data.backward = import_edge.isBackward();
}
if(edge.source == edge.target) {
continue;
if( edge.source == edge.target ) {
continue;
}
edge.data.distance = (std::max)((int)import_edge.weight(), 1 );
BOOST_ASSERT( edge.data.distance > 0 );
edge.data.shortcut = false;
edge.data.roundabout = import_edge.isRoundabout();
edge.data.ignoreInGrid = import_edge.ignoreInGrid();
edge.data.ignore_in_grid = import_edge.ignoreInGrid();
edge.data.nameID = import_edge.name();
edge.data.type = import_edge.type();
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
edge.data.edgeBasedNodeID = edges_list.size();
edge.data.contraFlow = import_edge.isContraFlow();
edges_list.push_back( edge );
if( edge.data.backward ) {
std::swap( edge.source, edge.target );
edge.data.forward = import_edge.isBackward();
edge.data.backward = import_edge.isForward();
edge.data.edgeBasedNodeID = edges_list.size();
if( !import_edge.IsSplit() ) {
using std::swap; //enable ADL
swap( edge.source, edge.target );
edge.data.SwapDirectionFlags();
edges_list.push_back( edge );
}
}
std::vector<ImportEdge>().swap(input_edge_list);
std::sort( edges_list.begin(), edges_list.end() );
m_node_based_graph = boost::make_shared<NodeBasedDynamicGraph>(
number_of_nodes, edges_list
number_of_nodes,
edges_list
);
DeallocatingVector<NodeBasedEdge>().swap(edges_list);
BOOST_ASSERT(0 == edges_list.size() );
}
void EdgeBasedGraphFactory::FixupArrivingTurnRestriction(
const NodeID u,
const NodeID v,
const NodeID w
) {
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
BOOST_ASSERT( v != std::numeric_limits<unsigned>::max() );
BOOST_ASSERT( w != std::numeric_limits<unsigned>::max() );
std::vector<NodeID> predecessors;
for(
EdgeID current_edge_id = m_node_based_graph->BeginEdges(u);
current_edge_id < m_node_based_graph->EndEdges(u);
++current_edge_id
) {
const EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge_id);
const NodeID target = m_node_based_graph->GetTarget(current_edge_id);
if( edge_data.backward && ( v != target) ) {
predecessors.push_back(target);
}
}
BOOST_FOREACH( const NodeID x, predecessors ) {
const std::pair<NodeID, NodeID> restr_start = std::make_pair(x,u);
RestrictionMap::const_iterator restriction_iterator;
restriction_iterator = m_restriction_map.find( restr_start );
if( restriction_iterator != m_restriction_map.end() ) {
const unsigned index = restriction_iterator->second;
BOOST_FOREACH(
RestrictionTarget & restriction_target,
m_restriction_bucket_list.at(index)
) {
if( v == restriction_target.first ) {
restriction_target.first = w;
}
}
}
}
}
void EdgeBasedGraphFactory::FixupStartingTurnRestriction(
const NodeID u,
const NodeID v,
const NodeID w
) {
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
BOOST_ASSERT( v != std::numeric_limits<unsigned>::max() );
BOOST_ASSERT( w != std::numeric_limits<unsigned>::max() );
const std::pair<NodeID, NodeID> old_start = std::make_pair(v,w);
RestrictionMap::const_iterator restriction_iterator;
restriction_iterator = m_restriction_map.find( old_start );
if( restriction_iterator != m_restriction_map.end() ) {
const unsigned index = restriction_iterator->second;
// remove old restriction start (v,w)
m_restriction_map.erase( restriction_iterator );
// insert new restriction start (u,w) (point to index)
const std::pair<NodeID, NodeID> new_start = std::make_pair(u,w);
m_restriction_map.insert( std::make_pair(new_start, index) );
}
}
void EdgeBasedGraphFactory::GetEdgeBasedEdges(
@ -146,8 +217,11 @@ void EdgeBasedGraphFactory::GetEdgeBasedEdges(
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
#ifndef NDEBUG
BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){
BOOST_ASSERT(node.lat1 != INT_MAX); BOOST_ASSERT(node.lon1 != INT_MAX);
BOOST_ASSERT(node.lat2 != INT_MAX); BOOST_ASSERT(node.lon2 != INT_MAX);
BOOST_ASSERT( m_node_info_list.at(node.u).lat != INT_MAX );
BOOST_ASSERT( m_node_info_list.at(node.u).lon != INT_MAX );
BOOST_ASSERT( m_node_info_list.at(node.v).lon != INT_MAX );
BOOST_ASSERT( m_node_info_list.at(node.v).lat != INT_MAX );
}
#endif
nodes.swap(m_edge_based_node_list);
@ -157,7 +231,9 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
const NodeID u,
const NodeID v
) const {
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
BOOST_ASSERT( v != std::numeric_limits<unsigned>::max() );
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restriction_iter;
restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter != m_restriction_map.end()) {
@ -171,7 +247,7 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
}
}
}
return UINT_MAX;
return std::numeric_limits<unsigned>::max();
}
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
@ -179,8 +255,11 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
const NodeID v,
const NodeID w
) const {
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
BOOST_ASSERT( v != std::numeric_limits<unsigned>::max() );
BOOST_ASSERT( w != std::numeric_limits<unsigned>::max() );
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restriction_iter;
restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter != m_restriction_map.end()) {
@ -189,7 +268,10 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
const RestrictionTarget & restriction_target,
m_restriction_bucket_list.at(index)
) {
if(w == restriction_target.first) {
if(
( w == restriction_target.first ) && // target found
( !restriction_target.second ) // and not an only_-restr.
) {
return true;
}
}
@ -198,22 +280,175 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
}
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
EdgeIterator e1,
NodeIterator u,
NodeIterator v,
bool belongsToTinyComponent) {
EdgeData & data = m_node_based_graph->GetEdgeData(e1);
EdgeBasedNode currentNode;
currentNode.nameID = data.nameID;
currentNode.lat1 = m_node_info_list[u].lat;
currentNode.lon1 = m_node_info_list[u].lon;
currentNode.lat2 = m_node_info_list[v].lat;
currentNode.lon2 = m_node_info_list[v].lon;
currentNode.belongsToTinyComponent = belongsToTinyComponent;
currentNode.id = data.edgeBasedNodeID;
currentNode.ignoreInGrid = data.ignoreInGrid;
currentNode.weight = data.distance;
m_edge_based_node_list.push_back(currentNode);
NodeIterator u,
NodeIterator v,
EdgeIterator e1,
bool belongs_to_tiny_cc
) {
// merge edges together into one EdgeBasedNode
BOOST_ASSERT( u != SPECIAL_NODEID );
BOOST_ASSERT( v != SPECIAL_NODEID );
BOOST_ASSERT( e1 != SPECIAL_EDGEID );
#ifndef NDEBUG
// find forward edge id and
const EdgeID e1b = m_node_based_graph->FindEdge(u, v);
BOOST_ASSERT( e1 == e1b );
#endif
BOOST_ASSERT( e1 != SPECIAL_EDGEID );
const EdgeData & forward_data = m_node_based_graph->GetEdgeData(e1);
// find reverse edge id and
const EdgeID e2 = m_node_based_graph->FindEdge(v, u);
#ifndef NDEBUG
if ( e2 == m_node_based_graph->EndEdges(v) ) {
SimpleLogger().Write(logWARNING) << "Did not find edge (" << v << "," << u << ")";
}
#endif
BOOST_ASSERT( e2 != SPECIAL_EDGEID );
BOOST_ASSERT( e2 < m_node_based_graph->EndEdges(v) );
const EdgeData & reverse_data = m_node_based_graph->GetEdgeData(e2);
if(
forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
reverse_data.edgeBasedNodeID == SPECIAL_NODEID
) {
return;
}
BOOST_ASSERT( m_geometry_compressor.HasEntryForID(e1) == m_geometry_compressor.HasEntryForID(e2) );
if( m_geometry_compressor.HasEntryForID(e1) ) {
BOOST_ASSERT( m_geometry_compressor.HasEntryForID(e2) );
// reconstruct geometry and put in each individual edge with its offset
const std::vector<GeometryCompressor::CompressedNode> & forward_geometry = m_geometry_compressor.GetBucketReference(e1);
const std::vector<GeometryCompressor::CompressedNode> & reverse_geometry = m_geometry_compressor.GetBucketReference(e2);
BOOST_ASSERT( forward_geometry.size() == reverse_geometry.size() );
BOOST_ASSERT( 0 != forward_geometry.size() );
// reconstruct bidirectional edge with individual weights and put each into the NN index
std::vector<int> forward_dist_prefix_sum(forward_geometry.size(), 0);
std::vector<int> reverse_dist_prefix_sum(reverse_geometry.size(), 0);
// quick'n'dirty prefix sum as std::partial_sum needs addtional casts
// TODO: move to lambda function with C++11
int temp_sum = 0;
for (unsigned i = 0; i < forward_geometry.size(); ++i)
{
forward_dist_prefix_sum[i] = temp_sum;
temp_sum += forward_geometry[i].second;
BOOST_ASSERT( forward_data.distance >= temp_sum );
}
temp_sum = 0;
for( unsigned i = 0; i < reverse_geometry.size(); ++i ) {
temp_sum += reverse_geometry[reverse_geometry.size()-1-i].second;
reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
BOOST_ASSERT( reverse_data.distance >= temp_sum );
}
BOOST_ASSERT( forward_geometry.size() == reverse_geometry.size() );
const unsigned geometry_size = forward_geometry.size();
BOOST_ASSERT( geometry_size > 1 );
NodeID current_edge_start_coordinate_id = u;
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
{
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
}
if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID)
{
max_id = std::max(reverse_data.edgeBasedNodeID, max_id);
}
// traverse arrays from start and end respectively
for( unsigned i = 0; i < geometry_size; ++i ) {
BOOST_ASSERT( current_edge_start_coordinate_id == reverse_geometry[geometry_size-1-i].first );
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
BOOST_ASSERT( current_edge_target_coordinate_id != current_edge_start_coordinate_id);
// build edges
m_edge_based_node_list.push_back(
EdgeBasedNode(
forward_data.edgeBasedNodeID,
reverse_data.edgeBasedNodeID,
current_edge_start_coordinate_id,
current_edge_target_coordinate_id,
forward_data.nameID,
forward_geometry[i].second,
reverse_geometry[i].second,
forward_dist_prefix_sum[i],
reverse_dist_prefix_sum[i],
m_geometry_compressor.GetPositionForID(e1),
i,
belongs_to_tiny_cc
)
);
current_edge_start_coordinate_id = current_edge_target_coordinate_id;
BOOST_ASSERT( m_edge_based_node_list.back().IsCompressed() );
BOOST_ASSERT(
u != m_edge_based_node_list.back().u ||
v != m_edge_based_node_list.back().v
);
BOOST_ASSERT(
u != m_edge_based_node_list.back().v ||
v != m_edge_based_node_list.back().u
);
}
BOOST_ASSERT( current_edge_start_coordinate_id == v );
BOOST_ASSERT( m_edge_based_node_list.back().IsCompressed() );
} else {
BOOST_ASSERT( !m_geometry_compressor.HasEntryForID(e2) );
if( forward_data.edgeBasedNodeID != std::numeric_limits<unsigned>::max() ) {
BOOST_ASSERT( forward_data.forward );
}
if( reverse_data.edgeBasedNodeID != std::numeric_limits<unsigned>::max() ) {
BOOST_ASSERT( reverse_data.forward );
}
if( forward_data.edgeBasedNodeID == std::numeric_limits<unsigned>::max() ) {
BOOST_ASSERT( !forward_data.forward );
}
if( reverse_data.edgeBasedNodeID == std::numeric_limits<unsigned>::max() ) {
BOOST_ASSERT( !reverse_data.forward );
}
BOOST_ASSERT(
forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
reverse_data.edgeBasedNodeID != SPECIAL_NODEID
);
//TODO C++11: emplace_back with
m_edge_based_node_list.push_back(
EdgeBasedNode(
forward_data.edgeBasedNodeID,
reverse_data.edgeBasedNodeID,
u,
v,
forward_data.nameID,
forward_data.distance,
reverse_data.distance,
0,
0,
SPECIAL_EDGEID,
0,
belongs_to_tiny_cc
)
);
BOOST_ASSERT( !m_edge_based_node_list.back().IsCompressed() );
}
}
@ -229,27 +464,173 @@ void EdgeBasedGraphFactory::FlushVectorToStream(
}
void EdgeBasedGraphFactory::Run(
const char * original_edge_data_filename,
const std::string & original_edge_data_filename,
const std::string & geometry_filename,
lua_State *lua_state
) {
SimpleLogger().Write() << "Compressing geometry of input graph";
//TODO: iterate over all turns
SimpleLogger().Write() << "Removing graph geometry while preserving topology";
//TODO: compress geometries
const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
//TODO: update turn restrictions if concerned by compression
Percent p(original_number_of_nodes);
unsigned removed_node_count = 0;
//TODO: do some compression statistics
for( NodeID v = 0; v < original_number_of_nodes; ++v ) {
p.printStatus(v);
// only contract degree 2 vertices
if( 2 != m_node_based_graph->GetOutDegree(v) ) {
continue;
}
// don't contract barrier node
if( m_barrier_nodes.end() != m_barrier_nodes.find(v) ) {
continue;
}
const bool reverse_edge_order = !(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(v)).forward);
const EdgeIterator forward_e2 = m_node_based_graph->BeginEdges(v) + reverse_edge_order;
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != forward_e2 );
const EdgeIterator reverse_e2 = m_node_based_graph->BeginEdges(v) + 1 - reverse_edge_order;
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != reverse_e2 );
const EdgeData & fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
const EdgeData & rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
const NodeIterator w = m_node_based_graph->GetTarget(forward_e2);
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != w );
BOOST_ASSERT( v != w );
const NodeIterator u = m_node_based_graph->GetTarget(reverse_e2);
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != u );
BOOST_ASSERT( u != v );
const EdgeIterator forward_e1 = m_node_based_graph->FindEdge(u, v);
BOOST_ASSERT( m_node_based_graph->EndEdges(u) != forward_e1 );
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != forward_e1 );
BOOST_ASSERT( v == m_node_based_graph->GetTarget(forward_e1));
const EdgeIterator reverse_e1 = m_node_based_graph->FindEdge(w, v);
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != reverse_e1 );
BOOST_ASSERT( v == m_node_based_graph->GetTarget(reverse_e1));
const EdgeData & fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
const EdgeData & rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
if(
( m_node_based_graph->FindEdge(u, w) != m_node_based_graph->EndEdges(u) ) ||
( m_node_based_graph->FindEdge(w, u) != m_node_based_graph->EndEdges(w) )
) {
continue;
}
if ( //TODO: rename to IsCompatibleTo
fwd_edge_data1.IsEqualTo(fwd_edge_data2) &&
rev_edge_data1.IsEqualTo(rev_edge_data2)
) {
//Get distances before graph is modified
const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance;
const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance;
BOOST_ASSERT( 0 != forward_weight1 );
BOOST_ASSERT( 0 != forward_weight2 );
const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance;
const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance;
BOOST_ASSERT( 0 != reverse_weight1 );
BOOST_ASSERT( 0 != forward_weight2 );
const bool add_traffic_signal_penalty = (m_traffic_lights.find(v) != m_traffic_lights.end());
// add weight of e2's to e1
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
if (add_traffic_signal_penalty)
{
m_node_based_graph->GetEdgeData(forward_e1).distance += speed_profile.trafficSignalPenalty;
m_node_based_graph->GetEdgeData(reverse_e1).distance += speed_profile.trafficSignalPenalty;
}
// extend e1's to targets of e2's
m_node_based_graph->SetTarget(forward_e1, w);
m_node_based_graph->SetTarget(reverse_e1, u);
// remove e2's (if bidir, otherwise only one)
m_node_based_graph->DeleteEdge(v, forward_e2);
m_node_based_graph->DeleteEdge(v, reverse_e2);
// update any involved turn restrictions
FixupStartingTurnRestriction( u, v, w );
FixupArrivingTurnRestriction( u, v, w );
FixupStartingTurnRestriction( w, v, u );
FixupArrivingTurnRestriction( w, v, u );
// store compressed geometry in container
m_geometry_compressor.CompressEdge(
forward_e1,
forward_e2,
v,
w,
forward_weight1 + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty :0),
forward_weight2
);
m_geometry_compressor.CompressEdge(
reverse_e1,
reverse_e2,
v,
u,
reverse_weight1 ,
reverse_weight2 + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty :0)
);
++removed_node_count;
BOOST_ASSERT
(
m_node_based_graph->GetEdgeData(forward_e1).nameID ==
m_node_based_graph->GetEdgeData(reverse_e1).nameID
);
}
}
SimpleLogger().Write() << "removed " << removed_node_count << " nodes";
m_geometry_compressor.PrintStatistics();
unsigned new_node_count = 0;
unsigned new_edge_count = 0;
for( unsigned i = 0; i < m_node_based_graph->GetNumberOfNodes(); ++i ) {
if( m_node_based_graph->GetOutDegree(i) > 0 ) {
++new_node_count;
new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i));
}
}
SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count;
SimpleLogger().Write() << "Node compression ratio: " << new_node_count/(double)original_number_of_nodes;
SimpleLogger().Write() << "Edge compression ratio: " << new_edge_count/(double)original_number_of_edges;
// renumber edge based node IDs
unsigned numbered_edges_count = 0;
for(NodeID current_node = 0; current_node < m_node_based_graph->GetNumberOfNodes(); ++current_node) {
for(EdgeIterator current_edge = m_node_based_graph->BeginEdges(current_node); current_edge < m_node_based_graph->EndEdges(current_node); ++current_edge) {
EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge);
if( !edge_data.forward ) {
continue;
}
BOOST_ASSERT( numbered_edges_count < m_node_based_graph->GetNumberOfEdges() );
edge_data.edgeBasedNodeID = numbered_edges_count;
++numbered_edges_count;
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != edge_data.edgeBasedNodeID);
}
}
SimpleLogger().Write() << "Identifying components of the road network";
unsigned skipped_turns_counter = 0;
unsigned node_based_edge_counter = 0;
unsigned original_edges_counter = 0;
std::ofstream edge_data_file(
original_edge_data_filename,
original_edge_data_filename.c_str(),
std::ios::binary
);
@ -261,49 +642,62 @@ void EdgeBasedGraphFactory::Run(
//Run a BFS on the undirected graph and identify small components
std::vector<unsigned> component_index_list;
std::vector<NodeID> component_index_size;
BFSCompentExplorer( component_index_list, component_index_size);
std::vector<NodeID > component_index_size;
BFSCompentExplorer( component_index_list, component_index_size );
SimpleLogger().Write() <<
"identified: " << component_index_size.size() << " many components";
SimpleLogger().Write() <<
"generating edge-expanded nodes";
SimpleLogger().Write() << "generating edge-expanded nodes";
Percent p(m_node_based_graph->GetNumberOfNodes());
//loop over all edges and generate new set of nodes.
p.reinit(m_node_based_graph->GetNumberOfNodes());
//loop over all edges and generate new set of nodes
for(
NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
u < end;
++u
) {
BOOST_ASSERT( u != std::numeric_limits<unsigned>::max() );
BOOST_ASSERT( u < m_node_based_graph->GetNumberOfNodes() );
p.printIncrement();
for(
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
EdgeID e1 = m_node_based_graph->BeginEdges(u),
last_edge = m_node_based_graph->EndEdges(u);
e1 < last_edge;
++e1
) {
NodeIterator v = m_node_based_graph->GetTarget(e1);
const EdgeData & edge_data = m_node_based_graph->GetEdgeData(e1);
if( edge_data.edgeBasedNodeID == SPECIAL_NODEID ) {
// continue;
}
BOOST_ASSERT( e1 != SPECIAL_EDGEID );
const NodeID v = m_node_based_graph->GetTarget(e1);
BOOST_ASSERT( SPECIAL_NODEID != v );
// pick only every other edge
if( u > v ) {
continue;
}
BOOST_ASSERT( u < v );
BOOST_ASSERT( edge_data.type != SHRT_MAX );
if(m_node_based_graph->GetEdgeData(e1).type != SHRT_MAX) {
BOOST_ASSERT_MSG(e1 != UINT_MAX, "edge id invalid");
BOOST_ASSERT_MSG(u != UINT_MAX, "souce node invalid");
BOOST_ASSERT_MSG(v != UINT_MAX, "target node invalid");
//Note: edges that end on barrier nodes or on a turn restriction
//may actually be in two distinct components. We choose the smallest
const unsigned size_of_component = std::min(
component_index_size[component_index_list[u]],
component_index_size[component_index_list[v]]
);
const unsigned size_of_component = std::min(
component_index_size[component_index_list[u]],
component_index_size[component_index_list[v]]
);
InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 );
}
const bool component_is_tiny = ( size_of_component < 1000 );
InsertEdgeBasedNode( u, v, e1, component_is_tiny );
}
}
SimpleLogger().Write()
<< "Generated " << m_edge_based_node_list.size() << " nodes in " <<
"edge-expanded graph";
m_number_of_edge_based_nodes = numbered_edges_count;
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() <<
" nodes in edge-expanded graph";
SimpleLogger().Write() << "generating edge-expanded edges";
std::vector<NodeID>().swap(component_index_size);
@ -322,6 +716,10 @@ void EdgeBasedGraphFactory::Run(
//Loop over all turns and generate new set of edges.
//Three nested loop look super-linear, but we are dealing with a (kind of)
//linear number of turns only.
unsigned restricted_turns_counter = 0;
unsigned skipped_uturns_counter = 0;
unsigned skipped_barrier_turns_counter = 0;
unsigned compressed = 0;
p.reinit(m_node_based_graph->GetNumberOfNodes());
for(
NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
@ -334,6 +732,10 @@ void EdgeBasedGraphFactory::Run(
e1 < last_edge_u;
++e1
) {
if( !m_node_based_graph->GetEdgeData(e1).forward ) {
continue;
}
++node_based_edge_counter;
const NodeIterator v = m_node_based_graph->GetTarget(e1);
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
@ -345,24 +747,28 @@ void EdgeBasedGraphFactory::Run(
e2 < last_edge_v;
++e2
) {
if( !m_node_based_graph->GetEdgeData(e2).forward ) {
continue;
}
const NodeIterator w = m_node_based_graph->GetTarget(e2);
if(
to_node_of_only_restriction != UINT_MAX &&
to_node_of_only_restriction != SPECIAL_NODEID &&
w != to_node_of_only_restriction
) {
//We are at an only_-restriction but not at the right turn.
++skipped_turns_counter;
++restricted_turns_counter;
continue;
}
if( is_barrier_node) {
if(u != w) {
++skipped_turns_counter;
++skipped_barrier_turns_counter;
continue;
}
} else {
if ( (u == w) && (m_node_based_graph->GetOutDegree(v) > 1) ) {
++skipped_turns_counter;
++skipped_uturns_counter;
continue;
}
}
@ -371,28 +777,20 @@ void EdgeBasedGraphFactory::Run(
//at the end of a dead-end street
if (
CheckIfTurnIsRestricted(u, v, w) &&
(to_node_of_only_restriction == UINT_MAX) &&
(to_node_of_only_restriction == SPECIAL_NODEID) &&
(w != to_node_of_only_restriction)
) {
++skipped_turns_counter;
++restricted_turns_counter;
continue;
}
//only add an edge if turn is not prohibited
const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1);
const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2);
const EdgeData & edge_data1 = m_node_based_graph->GetEdgeData(e1);
const EdgeData & edge_data2 = m_node_based_graph->GetEdgeData(e2);
BOOST_ASSERT(
edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges()
);
BOOST_ASSERT(
edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges()
);
BOOST_ASSERT(
edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID
);
BOOST_ASSERT( edge_data1.forward );
BOOST_ASSERT( edge_data2.forward );
BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
BOOST_ASSERT(edge_data1.forward);
BOOST_ASSERT(edge_data2.forward);
// the following is the core of the loop.
unsigned distance = edge_data1.distance;
@ -400,19 +798,27 @@ void EdgeBasedGraphFactory::Run(
distance += speed_profile.trafficSignalPenalty;
}
const int turn_penalty = GetTurnPenalty(u, v, w, lua_state);
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
if(turnInstruction == TurnInstructions.UTurn){
TurnInstruction turn_instruction = AnalyzeTurn(u, v, w);
if(turn_instruction == TurnInstructionsClass::UTurn){
distance += speed_profile.uTurnPenalty;
}
distance += turn_penalty;
const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1);
if(edge_is_compressed) {
++compressed;
}
original_edge_data_vector.push_back(
OriginalEdgeData(
v,
edge_data2.nameID,
turnInstruction
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v),
edge_data1.nameID,
turn_instruction,
edge_is_compressed
)
);
++original_edges_counter;
if(original_edge_data_vector.size() > 100000) {
@ -422,6 +828,9 @@ void EdgeBasedGraphFactory::Run(
);
}
BOOST_ASSERT( SPECIAL_NODEID != edge_data1.edgeBasedNodeID );
BOOST_ASSERT( SPECIAL_NODEID != edge_data2.edgeBasedNodeID );
m_edge_based_edge_list.push_back(
EdgeBasedEdge(
edge_data1.edgeBasedNodeID,
@ -442,17 +851,16 @@ void EdgeBasedGraphFactory::Run(
edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) );
edge_data_file.close();
SimpleLogger().Write() <<
"Generated " << m_edge_based_node_list.size() << " edge based nodes";
SimpleLogger().Write() <<
"Node-based graph contains " << node_based_edge_counter << " edges";
SimpleLogger().Write() <<
"Edge-expanded graph ...";
SimpleLogger().Write() <<
" contains " << m_edge_based_edge_list.size() << " edges";
SimpleLogger().Write() <<
" skips " << skipped_turns_counter << " turns, "
"defined by " << m_turn_restrictions_count << " restrictions";
m_geometry_compressor.SerializeInternalVector( geometry_filename );
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes";
SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges";
SimpleLogger().Write() << "Edge-expanded graph ...";
SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges";
SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, "
"defined by " << m_turn_restrictions_count << " restrictions";
SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns";
SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
}
int EdgeBasedGraphFactory::GetTurnPenalty(
@ -488,7 +896,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
const NodeID w
) const {
if(u == w) {
return TurnInstructions.UTurn;
return TurnInstructionsClass::UTurn;
}
const EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
@ -498,10 +906,10 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
const EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
if(!data1.contraFlow && data2.contraFlow) {
return TurnInstructions.EnterAgainstAllowedDirection;
return TurnInstructionsClass::EnterAgainstAllowedDirection;
}
if(data1.contraFlow && !data2.contraFlow) {
return TurnInstructions.LeaveAgainstAllowedDirection;
return TurnInstructionsClass::LeaveAgainstAllowedDirection;
}
//roundabouts need to be handled explicitely
@ -509,19 +917,19 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
//Is a turn possible? If yes, we stay on the roundabout!
if( 1 == m_node_based_graph->GetOutDegree(v) ) {
//No turn possible.
return TurnInstructions.NoTurn;
return TurnInstructionsClass::NoTurn;
}
return TurnInstructions.StayOnRoundAbout;
return TurnInstructionsClass::StayOnRoundAbout;
}
//Does turn start or end on roundabout?
if(data1.roundabout || data2.roundabout) {
//We are entering the roundabout
if( (!data1.roundabout) && data2.roundabout) {
return TurnInstructions.EnterRoundAbout;
return TurnInstructionsClass::EnterRoundAbout;
}
//We are leaving the roundabout
if(data1.roundabout && (!data2.roundabout) ) {
return TurnInstructions.LeaveRoundAbout;
return TurnInstructionsClass::LeaveRoundAbout;
}
}
@ -531,9 +939,9 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
//TODO: Here we should also do a small graph exploration to check for
// more complex situations
if( 0 != data1.nameID ) {
return TurnInstructions.NoTurn;
return TurnInstructionsClass::NoTurn;
} else if (m_node_based_graph->GetOutDegree(v) <= 2) {
return TurnInstructions.NoTurn;
return TurnInstructionsClass::NoTurn;
}
}
@ -542,11 +950,11 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
m_node_info_list[v],
m_node_info_list[w]
);
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
}
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
return m_node_based_graph->GetNumberOfEdges();
unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const {
return m_number_of_edge_based_nodes;
}
void EdgeBasedGraphFactory::BFSCompentExplorer(
@ -563,12 +971,12 @@ void EdgeBasedGraphFactory::BFSCompentExplorer(
component_index_list.resize(
m_node_based_graph->GetNumberOfNodes(),
UINT_MAX
std::numeric_limits<unsigned>::max()
);
//put unexplorered node with parent pointer into queue
for( NodeID node = 0, end = m_node_based_graph->GetNumberOfNodes(); node < end; ++node) {
if(UINT_MAX == component_index_list[node]) {
if(std::numeric_limits<unsigned>::max() == component_index_list[node]) {
bfs_queue.push(std::make_pair(node, node));
//mark node as read
component_index_list[node] = current_component;
@ -594,7 +1002,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer(
NodeIterator w = m_node_based_graph->GetTarget(e2);
if(
to_node_of_only_restriction != UINT_MAX &&
to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
w != to_node_of_only_restriction
) {
// At an only_-restriction but not at the right turn
@ -605,7 +1013,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer(
//when it is at the end of a dead-end street.
if (!CheckIfTurnIsRestricted(u, v, w) ) {
//only add an edge if turn is not prohibited
if(UINT_MAX == component_index_list[w]) {
if(std::numeric_limits<unsigned>::max() == component_index_list[w]) {
//insert next (node, parent) only if w has
//not yet been explored
//mark node as read

View File

@ -53,23 +53,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/unordered_set.hpp>
#include <algorithm>
#include <fstream>
#include <iosfwd>
#include <queue>
#include <vector>
class EdgeBasedGraphFactory : boost::noncopyable {
public:
struct SpeedProfileProperties{
SpeedProfileProperties() :
trafficSignalPenalty(0),
uTurnPenalty(0),
has_turn_penalty_function(false)
{ }
int trafficSignalPenalty;
int uTurnPenalty;
bool has_turn_penalty_function;
} speed_profile;
struct SpeedProfileProperties;
explicit EdgeBasedGraphFactory(
int number_of_nodes,
@ -78,10 +68,14 @@ public:
std::vector<NodeID> & traffic_light_node_list,
std::vector<TurnRestriction> & input_restrictions_list,
std::vector<NodeInfo> & m_node_info_list,
SpeedProfileProperties speed_profile
SpeedProfileProperties & speed_profile
);
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
void Run(
const std::string & original_edge_data_filename,
const std::string & geometry_filename,
lua_State *myLuaState
);
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
@ -100,10 +94,27 @@ public:
lua_State *myLuaState
) const;
unsigned GetNumberOfNodes() const;
unsigned GetNumberOfEdgeBasedNodes() const;
struct SpeedProfileProperties{
SpeedProfileProperties() :
trafficSignalPenalty(0),
uTurnPenalty(0),
has_turn_penalty_function(false)
{ }
int trafficSignalPenalty;
int uTurnPenalty;
bool has_turn_penalty_function;
} speed_profile;
private:
struct NodeBasedEdgeData {
NodeBasedEdgeData() {
//TODO: proper c'tor
edgeBasedNodeID = UINT_MAX;
}
int distance;
unsigned edgeBasedNodeID;
unsigned nameID;
@ -113,11 +124,26 @@ private:
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignoreInGrid:1;
bool ignore_in_grid:1;
bool contraFlow:1;
void SwapDirectionFlags() {
bool temp_flag = forward;
forward = backward;
backward = temp_flag;
}
bool IsEqualTo( const NodeBasedEdgeData & other ) const {
return (forward == other.forward) &&
(backward == other.backward) &&
(nameID == other.nameID) &&
(ignore_in_grid == other.ignore_in_grid) &&
(contraFlow == other.contraFlow);
}
};
unsigned m_turn_restrictions_count;
unsigned m_number_of_edge_based_nodes;
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
@ -139,6 +165,7 @@ private:
boost::unordered_set<NodeID> m_traffic_lights;
RestrictionMap m_restriction_map;
GeometryCompressor m_geometry_compressor;
NodeID CheckForEmanatingIsOnlyTurn(
const NodeID u,
@ -152,9 +179,9 @@ private:
) const;
void InsertEdgeBasedNode(
NodeBasedDynamicGraph::EdgeIterator e1,
NodeBasedDynamicGraph::NodeIterator u,
NodeBasedDynamicGraph::NodeIterator v,
NodeBasedDynamicGraph::EdgeIterator e1,
bool belongsToTinyComponent
);
@ -167,6 +194,20 @@ private:
std::ofstream & edge_data_file,
std::vector<OriginalEdgeData> & original_edge_data_vector
) const;
void FixupArrivingTurnRestriction(
const NodeID u,
const NodeID v,
const NodeID w
);
void FixupStartingTurnRestriction(
const NodeID u,
const NodeID v,
const NodeID w
);
unsigned max_id;
};
#endif /* EDGEBASEDGRAPHFACTORY_H_ */

View File

@ -26,69 +26,199 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "GeometryCompressor.h"
#include "../Util/SimpleLogger.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <limits>
int current_free_list_maximum = 0;
int UniqueNumber () { return ++current_free_list_maximum; }
int UniqueNumber() { return ++current_free_list_maximum; }
GeometryCompressor::GeometryCompressor() {
m_free_list.resize(100);
GeometryCompressor::GeometryCompressor()
{
m_free_list.reserve(100);
IncreaseFreeList();
}
void GeometryCompressor::IncreaseFreeList() {
void GeometryCompressor::IncreaseFreeList()
{
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
std::generate_n (m_free_list.rend(), 100, UniqueNumber);
for (unsigned i = 100; i > 0; --i)
{
m_free_list.push_back(current_free_list_maximum);
++current_free_list_maximum;
}
}
void GeometryCompressor::AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id ) {
//check if node_id already has a list
boost::unordered_map<unsigned, unsigned>::const_iterator map_iterator;
map_iterator = m_node_id_to_index_map.find( node_id );
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
{
return (m_edge_id_to_list_index_map.find(edge_id) != m_edge_id_to_list_index_map.end());
}
unsigned geometry_bucket_index = std::numeric_limits<unsigned>::max();
if( m_node_id_to_index_map.end() == map_iterator ) {
//if not, create one
if( m_free_list.empty() ) {
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
{
boost::unordered_map<EdgeID, unsigned>::const_iterator map_iterator;
map_iterator = m_edge_id_to_list_index_map.find(edge_id);
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
return map_iterator->second;
}
void GeometryCompressor::SerializeInternalVector(const std::string &path) const
{
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary|std::ios::out);
const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1;
BOOST_ASSERT(UINT_MAX != number_of_compressed_geometries);
geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned));
// write indices array
unsigned prefix_sum_of_list_indices = 0;
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
{
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
const std::vector<CompressedNode> &current_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> &current_vector = m_compressed_geometries[i];
const unsigned unpacked_size = current_vector.size();
control_sum += unpacked_size;
BOOST_ASSERT(UINT_MAX != unpacked_size);
BOOST_FOREACH (const CompressedNode current_node, current_vector)
{
geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID));
}
}
BOOST_ASSERT(control_sum == prefix_sum_of_list_indices);
// all done, let's close the resource
geometry_out_stream.close();
}
void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
const EdgeID edge_id_2,
const NodeID via_node_id,
const NodeID target_node_id,
const EdgeWeight weight1,
const EdgeWeight weight2)
{
// remove super-trivial geometries
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
BOOST_ASSERT(std::numeric_limits<int>::max() != weight1);
BOOST_ASSERT(std::numeric_limits<int>::max() != weight2);
// append list of removed edge_id plus via node to surviving edge id:
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
//
// General scheme:
// 1. append via node id to list of edge_id_1
// 2. find list for edge_id_2, if yes add all elements and delete it
// Add via node id. List is created if it does not exist
if (!HasEntryForID(edge_id_1))
{
// create a new entry in the map
if (0 == m_free_list.size())
{
// make sure there is a place to put the entries
IncreaseFreeList();
}
geometry_bucket_index = m_free_list.back();
BOOST_ASSERT(!m_free_list.empty());
m_edge_id_to_list_index_map[edge_id_1] = m_free_list.back();
m_free_list.pop_back();
} else {
geometry_bucket_index = map_iterator->second;
}
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != geometry_bucket_index );
BOOST_ASSERT( geometry_bucket_index < m_compressed_geometries.size() );
const unsigned edge_bucket_id1 = m_edge_id_to_list_index_map[edge_id_1];
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
//append contracted_node_id to m_compressed_geometries[node_id]
m_compressed_geometries[geometry_bucket_index].push_back(contracted_node_id);
std::vector<CompressedNode> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
//append m_compressed_geometries[contracted_node_id] to m_compressed_geometries[node_id]
map_iterator = m_node_id_to_index_map.find(contracted_node_id);
if ( m_node_id_to_index_map.end() != map_iterator) {
const unsigned bucket_index_to_remove = map_iterator->second;
BOOST_ASSERT( bucket_index_to_remove < m_compressed_geometries.size() );
if (edge_bucket_list1.empty())
{
edge_bucket_list1.push_back(std::make_pair(via_node_id, weight1));
}
m_compressed_geometries[geometry_bucket_index].insert(
m_compressed_geometries[geometry_bucket_index].end(),
m_compressed_geometries[bucket_index_to_remove].begin(),
m_compressed_geometries[bucket_index_to_remove].end()
);
//remove m_compressed_geometries[contracted_node_id], add to free list
m_compressed_geometries[bucket_index_to_remove].clear();
m_free_list.push_back(bucket_index_to_remove);
BOOST_ASSERT(0 < edge_bucket_list1.size());
BOOST_ASSERT(!edge_bucket_list1.empty());
if (HasEntryForID(edge_id_2))
{
// second edge is not atomic anymore
const unsigned list_to_remove_index = GetPositionForID(edge_id_2);
BOOST_ASSERT(list_to_remove_index < m_compressed_geometries.size());
std::vector<CompressedNode> &edge_bucket_list2 =
m_compressed_geometries[list_to_remove_index];
// found an existing list, append it to the list of edge_id_1
edge_bucket_list1.insert(
edge_bucket_list1.end(), edge_bucket_list2.begin(), edge_bucket_list2.end());
// remove the list of edge_id_2
m_edge_id_to_list_index_map.erase(edge_id_2);
BOOST_ASSERT(m_edge_id_to_list_index_map.end() ==
m_edge_id_to_list_index_map.find(edge_id_2));
edge_bucket_list2.clear();
BOOST_ASSERT(0 == edge_bucket_list2.size());
m_free_list.push_back(list_to_remove_index);
BOOST_ASSERT(list_to_remove_index == m_free_list.back());
}
else
{
// we are certain that the second edge is atomic.
edge_bucket_list1.push_back(std::make_pair(target_node_id, weight2));
}
}
void GeometryCompressor::PrintStatistics() const {
unsigned compressed_node_count = 0;
const unsigned surviving_node_count = m_compressed_geometries.size();
void GeometryCompressor::PrintStatistics() const
{
const uint64_t compressed_edges = m_compressed_geometries.size();
BOOST_ASSERT(0 == compressed_edges % 2);
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
BOOST_FOREACH(const std::vector<unsigned> & current_vector, m_compressed_geometries) {
compressed_node_count += current_vector.size();
uint64_t number_of_compressed_geometries = 0;
uint64_t longest_chain_length = 0;
BOOST_FOREACH (const std::vector<CompressedNode> &current_vector, m_compressed_geometries)
{
number_of_compressed_geometries += current_vector.size();
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
}
SimpleLogger().Write() <<
"surv: " << surviving_node_count <<
", comp: " << compressed_node_count <<
", comp ratio: " << ((float)surviving_node_count/std::max(compressed_node_count, 1u) );
SimpleLogger().Write() << "Geometry successfully removed:"
"\n compressed edges: " << compressed_edges
<< "\n compressed geometries: " << number_of_compressed_geometries
<< "\n longest chain length: " << longest_chain_length
<< "\n cmpr ratio: "
<< ((float)compressed_edges /
std::max(number_of_compressed_geometries, (uint64_t)1))
<< "\n avg chain length: "
<< (float)number_of_compressed_geometries /
std::max((uint64_t)1, compressed_edges);
}
const std::vector<GeometryCompressor::CompressedNode> &
GeometryCompressor::GetBucketReference(const EdgeID edge_id) const
{
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
return m_compressed_geometries.at(index);
}

View File

@ -25,34 +25,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/unordered_map.hpp>
#include <algorithm>
#include <limits>
#include <vector>
#ifndef GEOMETRY_COMPRESSOR_H
#define GEOMETRY_COMPRESSOR_H
class GeometryCompressor {
public:
class GeometryCompressor
{
public:
typedef std::pair<NodeID, EdgeWeight> CompressedNode;
GeometryCompressor();
void AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id );
void CompressEdge(const EdgeID surviving_edge_id,
const EdgeID removed_edge_id,
const NodeID via_node_id,
const NodeID target_node,
const EdgeWeight weight1,
const EdgeWeight weight2);
bool HasEntryForID(const EdgeID edge_id) const;
void PrintStatistics() const;
void SerializeInternalVector(const std::string &path) const;
unsigned GetPositionForID(const EdgeID edge_id) const;
const std::vector<GeometryCompressor::CompressedNode> &
GetBucketReference(const EdgeID edge_id) const;
private:
private:
void IncreaseFreeList();
std::vector<std::vector<unsigned> > m_compressed_geometries;
std::vector<std::vector<CompressedNode> > m_compressed_geometries;
std::vector<unsigned> m_free_list;
boost::unordered_map<unsigned, unsigned> m_node_id_to_index_map;
boost::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
};
#endif //GEOMETRY_COMPRESSOR_H
#endif // GEOMETRY_COMPRESSOR_H

View File

@ -96,6 +96,11 @@ public:
return nodes[node];
}
Key const & operator[]( const NodeID node ) const {
UnorderedMapConstIterator iter = nodes.find(node);
return iter->second;
}
void Clear() {
nodes.clear();
}
@ -158,6 +163,11 @@ public:
return insertedNodes[index].data;
}
Data const & GetData( NodeID node ) const {
const Key index = nodeIndex[node];
return insertedNodes[index].data;
}
Weight& GetKey( NodeID node ) {
const Key index = nodeIndex[node];
return insertedNodes[index].weight;

View File

@ -26,28 +26,45 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <osrm/Coordinate.h>
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#include <cmath>
#include <climits>
#ifndef NDEBUG
#include <bitset>
#endif
#include <iostream>
#include <limits>
FixedPointCoordinate::FixedPointCoordinate()
: lat(INT_MIN),
lon(INT_MIN)
: lat(std::numeric_limits<int>::min()),
lon(std::numeric_limits<int>::min())
{ }
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon)
: lat(lat),
lon(lon)
{ }
{
#ifndef NDEBUG
if(0 != (std::abs(lat) >> 30)) {
std::bitset<32> y(lat);
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
}
if(0 != (std::abs(lon) >> 30)) {
std::bitset<32> x(lon);
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
}
#endif
}
void FixedPointCoordinate::Reset() {
lat = INT_MIN;
lon = INT_MIN;
lat = std::numeric_limits<int>::min();
lon = std::numeric_limits<int>::min();
}
bool FixedPointCoordinate::isSet() const {
return (INT_MIN != lat) && (INT_MIN != lon);
return (std::numeric_limits<int>::min() != lat) &&
(std::numeric_limits<int>::min() != lon);
}
bool FixedPointCoordinate::isValid() const {
if(
@ -70,10 +87,10 @@ double FixedPointCoordinate::ApproximateDistance(
const int lat2,
const int lon2
) {
BOOST_ASSERT(lat1 != INT_MIN);
BOOST_ASSERT(lon1 != INT_MIN);
BOOST_ASSERT(lat2 != INT_MIN);
BOOST_ASSERT(lon2 != INT_MIN);
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1/COORDINATE_PRECISION;
double ln1 = lon1/COORDINATE_PRECISION;
@ -108,10 +125,10 @@ double FixedPointCoordinate::ApproximateEuclideanDistance(
const FixedPointCoordinate &c1,
const FixedPointCoordinate &c2
) {
BOOST_ASSERT(c1.lat != INT_MIN);
BOOST_ASSERT(c1.lon != INT_MIN);
BOOST_ASSERT(c2.lat != INT_MIN);
BOOST_ASSERT(c2.lon != INT_MIN);
BOOST_ASSERT(c1.lat != std::numeric_limits<int>::min());
BOOST_ASSERT(c1.lon != std::numeric_limits<int>::min());
BOOST_ASSERT(c2.lat != std::numeric_limits<int>::min());
BOOST_ASSERT(c2.lon != std::numeric_limits<int>::min());
const double RAD = 0.017453292519943295769236907684886;
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
@ -160,3 +177,7 @@ void FixedPointCoordinate::convertInternalReversedCoordinateToString(
convertInternalLatLonToString(coord.lon, tmp);
output += tmp;
}
void FixedPointCoordinate::Output(std::ostream & out) const {//, FixedPointCoordinate & c) {
out << "(" << lat/COORDINATE_PRECISION << "," << lon/COORDINATE_PRECISION << ")";
}

View File

@ -1,176 +1,160 @@
#ifndef EDGE_BASED_NODE_H
#define EDGE_BASED_NODE_H
#include <cmath>
#include <boost/assert.hpp>
#include "../Util/MercatorUtil.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
// An EdgeBasedNode represents a node in the edge-expanded graph.
#include <boost/assert.hpp>
#include <limits>
struct EdgeBasedNode {
EdgeBasedNode() :
id(INT_MAX),
lat1(INT_MAX),
lat2(INT_MAX),
lon1(INT_MAX),
lon2(INT_MAX >> 1),
belongsToTinyComponent(false),
nameID(UINT_MAX),
weight(UINT_MAX >> 1),
ignoreInGrid(false)
forward_edge_based_node_id(SPECIAL_NODEID),
reverse_edge_based_node_id(SPECIAL_NODEID),
u(SPECIAL_NODEID),
v(SPECIAL_NODEID),
name_id(0),
forward_weight(INVALID_EDGE_WEIGHT >> 1),
reverse_weight(INVALID_EDGE_WEIGHT >> 1),
forward_offset(0),
reverse_offset(0),
packed_geometry_id(SPECIAL_EDGEID),
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
belongsToTinyComponent(false)
{ }
// Computes:
// - the distance from the given query location to nearest point on this edge (and returns it)
// - the location on this edge which is nearest to the query location
// - the ratio ps:pq, where p and q are the end points of this edge, and s is the perpendicular foot of
// the query location on the line defined by p and q.
double ComputePerpendicularDistance(
const FixedPointCoordinate& query_location,
explicit EdgeBasedNode(
NodeID forward_edge_based_node_id,
NodeID reverse_edge_based_node_id,
NodeID u,
NodeID v,
unsigned name_id,
int forward_weight,
int reverse_weight,
int forward_offset,
int reverse_offset,
unsigned packed_geometry_id,
unsigned short fwd_segment_position,
bool belongs_to_tiny_component
) :
forward_edge_based_node_id(forward_edge_based_node_id),
reverse_edge_based_node_id(reverse_edge_based_node_id),
u(u),
v(v),
name_id(name_id),
forward_weight(forward_weight),
reverse_weight(reverse_weight),
forward_offset(forward_offset),
reverse_offset(reverse_offset),
packed_geometry_id(packed_geometry_id),
fwd_segment_position(fwd_segment_position),
belongsToTinyComponent(belongs_to_tiny_component)
{
BOOST_ASSERT(
( forward_edge_based_node_id != SPECIAL_NODEID ) ||
( reverse_edge_based_node_id != SPECIAL_NODEID )
);
}
inline static double ComputePerpendicularDistance(
const FixedPointCoordinate & coord_a,
const FixedPointCoordinate & coord_b,
const FixedPointCoordinate & query_location,
FixedPointCoordinate & nearest_location,
double & ratio,
double precision = COORDINATE_PRECISION
) const {
double & r
) {
BOOST_ASSERT( query_location.isValid() );
const double epsilon = 1.0/precision;
const double x = lat2y(query_location.lat/COORDINATE_PRECISION);
const double y = query_location.lon/COORDINATE_PRECISION;
const double a = lat2y(coord_a.lat/COORDINATE_PRECISION);
const double b = coord_a.lon/COORDINATE_PRECISION;
const double c = lat2y(coord_b.lat/COORDINATE_PRECISION);
const double d = coord_b.lon/COORDINATE_PRECISION;
double p,q/*,mX*/,nY;
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
const double m = (d-b)/(c-a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
q = b + m*(p - a);
} else {
p = c;
q = y;
}
nY = (d*p - c*q)/(a*d - b*c);
if( ignoreInGrid ) {
return std::numeric_limits<double>::max();
//discretize the result to coordinate precision. it's a hack!
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
nY = 0.;
}
// p, q : the end points of the underlying edge
const Point p(lat2y(lat1/COORDINATE_PRECISION), lon1/COORDINATE_PRECISION);
const Point q(lat2y(lat2/COORDINATE_PRECISION), lon2/COORDINATE_PRECISION);
// r : query location
const Point r(lat2y(query_location.lat/COORDINATE_PRECISION),
query_location.lon/COORDINATE_PRECISION);
const Point foot = ComputePerpendicularFoot(p, q, r, epsilon);
ratio = ComputeRatio(p, q, foot, epsilon);
BOOST_ASSERT( !std::isnan(ratio) );
nearest_location = ComputeNearestPointOnSegment(foot, ratio);
r = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
if( std::isnan(r) ) {
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
r = 0.;
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
r = 1.;
}
BOOST_ASSERT( !std::isnan(r) );
if( r <= 0. ){
nearest_location.lat = coord_a.lat;
nearest_location.lon = coord_a.lon;
} else if( r >= 1. ){
nearest_location.lat = coord_b.lat;
nearest_location.lon = coord_b.lon;
} else {
// point lies in between
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
nearest_location.lon = q*COORDINATE_PRECISION;
}
BOOST_ASSERT( nearest_location.isValid() );
// TODO: Replace with euclidean approximation when k-NN search is done
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(query_location, nearest_location);
BOOST_ASSERT( 0.0 <= approximated_distance );
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(
query_location,
nearest_location
);
BOOST_ASSERT( 0. <= approximated_distance );
return approximated_distance;
}
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
static inline FixedPointCoordinate Centroid(
const FixedPointCoordinate & a,
const FixedPointCoordinate & b
) {
FixedPointCoordinate centroid;
//The coordinates of the midpoint are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (std::min(a.lon, b.lon) + std::max(a.lon, b.lon))/2;
centroid.lat = (std::min(a.lat, b.lat) + std::max(a.lat, b.lat))/2;
return centroid;
}
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
// Returns the midpoint of the underlying edge.
inline FixedPointCoordinate Centroid() const {
return FixedPointCoordinate((lat1+lat2)/2, (lon1+lon2)/2);
}
NodeID id;
// The coordinates of the end-points of the underlying edge.
int lat1;
int lat2;
int lon1;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
// The weight of the underlying edge.
unsigned weight:31;
bool ignoreInGrid:1;
private:
typedef std::pair<double,double> Point;
// Compute the perpendicular foot of point r on the line defined by p and q.
Point ComputePerpendicularFoot(const Point &p, const Point &q, const Point &r, double epsilon) const {
// the projection of r onto the line pq
double foot_x, foot_y;
const bool is_parallel_to_y_axis = std::abs(q.first - p.first) < epsilon;
if( is_parallel_to_y_axis ) {
foot_x = q.first;
foot_y = r.second;
} else {
// the slope of the line through (a|b) and (c|d)
const double m = (q.second - p.second) / (q.first - p.first);
// Projection of (x|y) onto the line joining (a|b) and (c|d).
foot_x = ((r.first + (m*r.second)) + (m*m*p.first - m*p.second))/(1.0 + m*m);
foot_y = p.second + m*(foot_x - p.first);
}
return Point(foot_x, foot_y);
}
// Compute the ratio of the line segment pr to line segment pq.
double ComputeRatio(const Point & p, const Point & q, const Point & r, double epsilon) const {
const bool is_parallel_to_x_axis = std::abs(q.second-p.second) < epsilon;
const bool is_parallel_to_y_axis = std::abs(q.first -p.first ) < epsilon;
double ratio;
if( !is_parallel_to_y_axis ) {
ratio = (r.first - p.first)/(q.first - p.first);
} else if( !is_parallel_to_x_axis ) {
ratio = (r.second - p.second)/(q.second - p.second);
} else {
// (a|b) and (c|d) are essentially the same point
// by convention, we set the ratio to 0 in this case
//ratio = ((lat2 == query_location.lat) && (lon2 == query_location.lon)) ? 1. : 0.;
ratio = 0.0;
}
// Round to integer if the ratio is close to 0 or 1.
if( std::abs(ratio) <= epsilon ) {
ratio = 0.0;
} else if( std::abs(ratio-1.0) <= epsilon ) {
ratio = 1.0;
}
return ratio;
}
// Computes the point on the segment pq which is nearest to a point r = p + lambda * (q-p).
// p and q are the end points of the underlying edge.
FixedPointCoordinate ComputeNearestPointOnSegment(const Point & r, double lambda) const {
if( lambda <= 0.0 ) {
return FixedPointCoordinate(lat1, lon1);
} else if( lambda >= 1.0 ) {
return FixedPointCoordinate(lat2, lon2);
}
// r lies between p and q
return FixedPointCoordinate(
y2lat(r.first)*COORDINATE_PRECISION,
r.second*COORDINATE_PRECISION
);
bool IsCompressed() {
return packed_geometry_id != SPECIAL_EDGEID;
}
NodeID forward_edge_based_node_id; // needed for edge-expanded graph
NodeID reverse_edge_based_node_id; // needed for edge-expanded graph
NodeID u; // indices into the coordinates array
NodeID v; // indices into the coordinates array
unsigned name_id; // id of the edge name
int forward_weight; // weight of the edge
int reverse_weight; // weight in the other direction (may be different)
int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice
int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
unsigned short fwd_segment_position; // segment id in a compressed geometry
bool belongsToTinyComponent;
};
#endif //EDGE_BASED_NODE_H

View File

@ -54,7 +54,7 @@ public:
return boost::cref(iter->second);
}
inline bool Holds( KeyT const & key) const {
inline const bool Holds( KeyT const & key) const {
if( super::find(key) == super::end() ) {
return false;
}

View File

@ -61,7 +61,8 @@ public:
bool ra,
bool ig,
bool ar,
bool cf
bool cf,
bool is_split
) : _source(s),
_target(t),
_name(n),
@ -72,7 +73,8 @@ public:
_roundabout(ra),
_ignoreInGrid(ig),
_accessRestricted(ar),
_contraFlow(cf)
_contraFlow(cf),
is_split(is_split)
{
if(ty < 0) {
throw OSRMException("negative edge type");
@ -93,6 +95,7 @@ public:
bool ignoreInGrid() const { return _ignoreInGrid; }
bool isAccessRestricted() const { return _accessRestricted; }
bool isContraFlow() const { return _contraFlow; }
bool IsSplit() const { return is_split; }
//TODO: names need to be fixed.
NodeID _source;
@ -106,6 +109,7 @@ public:
bool _ignoreInGrid:1;
bool _accessRestricted:1;
bool _contraFlow:1;
bool is_split:1;
private:
NodeBasedEdge() { }
@ -162,7 +166,7 @@ public:
m_weight(w),
m_forward(f),
m_backward(b)
{}
{ }
NodeID target() const { return m_target; }
NodeID source() const { return m_source; }

View File

@ -44,11 +44,17 @@ struct ExternalMemoryNode : NodeInfo {
bollard(bollard),
trafficLight(traffic_light)
{ }
ExternalMemoryNode() : bollard(false), trafficLight(false) {}
ExternalMemoryNode()
:
bollard(false),
trafficLight(false)
{ }
static ExternalMemoryNode min_value() {
return ExternalMemoryNode(0,0,0, false, false);
}
static ExternalMemoryNode max_value() {
return ExternalMemoryNode(
std::numeric_limits<int>::max(),
@ -58,9 +64,11 @@ struct ExternalMemoryNode : NodeInfo {
false
);
}
NodeID key() const {
return id;
}
bool bollard;
bool trafficLight;
};

View File

@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INPUTREADERFACTORY_H
#define INPUTREADERFACTORY_H
#include <boost/assert.hpp>
#include <bzlib.h>
#include <libxml/xmlreader.h>
@ -51,21 +53,21 @@ int readFromBz2Stream( void* pointer, char* buffer, int len ) {
return read;
} else if(BZ_STREAM_END == context->error) {
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadGetUnused" <<std::endl; exit(-1);};
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused");
unusedTmp = (char*)unusedTmpVoid;
for(int i=0;i<context->nUnused;i++) {
context->unused[i] = unusedTmp[i];
}
BZ2_bzReadClose(&context->error, context->bz2);
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadClose" <<std::endl; exit(-1);};
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose");
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
if(0 == context->nUnused && feof(context->file)) {
return read;
} else {
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
if(NULL == context->bz2){std::cerr << "Could not open file" <<std::endl; exit(-1);};
BOOST_ASSERT_MSG(NULL != context->bz2, "Could not open file");
}
} else { std::cerr << "Could not read bz2 file" << std::endl; exit(-1); }
} else { BOOST_ASSERT_MSG(false, "Could not read bz2 file"); }
}
return read;
}

View File

@ -31,28 +31,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "TurnInstructions.h"
#include "../typedefs.h"
#include <climits>
#include <limits>
struct OriginalEdgeData{
explicit OriginalEdgeData(
NodeID via_node,
unsigned name_id,
TurnInstruction turn_instruction
TurnInstruction turn_instruction,
bool compressed_geometry
) :
via_node(via_node),
name_id(name_id),
turn_instruction(turn_instruction)
via_node( via_node ),
name_id( name_id ),
turn_instruction( turn_instruction ),
compressed_geometry( compressed_geometry )
{ }
OriginalEdgeData() :
via_node(UINT_MAX),
name_id(UINT_MAX),
turn_instruction(UCHAR_MAX)
via_node( std::numeric_limits<unsigned>::max() ),
name_id( std::numeric_limits<unsigned>::max() ),
turn_instruction( std::numeric_limits<unsigned char>::max() ),
compressed_geometry( false )
{ }
NodeID via_node;
unsigned name_id;
TurnInstruction turn_instruction;
bool compressed_geometry;
};
#endif //ORIGINAL_EDGE_DATA_H

View File

@ -29,75 +29,145 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define PHANTOMNODES_H_
#include <osrm/Coordinate.h>
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
struct PhantomNode {
struct PhantomNode
{
PhantomNode() :
edgeBasedNode(UINT_MAX),
nodeBasedEdgeNameID(UINT_MAX),
weight1(INT_MAX),
weight2(INT_MAX),
ratio(0.)
forward_node_id(SPECIAL_NODEID),
reverse_node_id(SPECIAL_NODEID),
name_id(std::numeric_limits<unsigned>::max()),
forward_weight(INVALID_EDGE_WEIGHT),
reverse_weight(INVALID_EDGE_WEIGHT),
forward_offset(0),
reverse_offset(0),
packed_geometry_id(SPECIAL_EDGEID),
fwd_segment_position(0)
{ }
NodeID edgeBasedNode;
unsigned nodeBasedEdgeNameID;
int weight1;
int weight2;
double ratio;
NodeID forward_node_id;
NodeID reverse_node_id;
unsigned name_id;
int forward_weight;
int reverse_weight;
int forward_offset;
int reverse_offset;
unsigned packed_geometry_id;
FixedPointCoordinate location;
void Reset() {
edgeBasedNode = UINT_MAX;
nodeBasedEdgeNameID = UINT_MAX;
weight1 = INT_MAX;
weight2 = INT_MAX;
ratio = 0.;
location.Reset();
}
bool isBidirected() const {
return weight2 != INT_MAX;
}
bool isValid(const unsigned numberOfNodes) const {
return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX);
unsigned short fwd_segment_position;
int GetForwardWeightPlusOffset() const
{
if (SPECIAL_NODEID == forward_node_id)
{
return 0;
}
const int result = (forward_offset + forward_weight);
return result;
}
bool operator==(const PhantomNode & other) const {
int GetReverseWeightPlusOffset() const
{
if (SPECIAL_NODEID == reverse_node_id)
{
return 0;
}
const int result = (reverse_offset + reverse_weight);
return result;
}
void Reset()
{
forward_node_id = SPECIAL_NODEID;
name_id = SPECIAL_NODEID;
forward_weight = INVALID_EDGE_WEIGHT;
reverse_weight = INVALID_EDGE_WEIGHT;
forward_offset = 0;
reverse_offset = 0;
location.Reset();
}
bool isBidirected() const
{
return (forward_node_id != SPECIAL_NODEID) &&
(reverse_node_id != SPECIAL_NODEID);
}
bool IsCompressed() const
{
return (forward_offset != 0) || (reverse_offset != 0);
}
bool isValid(const unsigned numberOfNodes) const
{
return
location.isValid() &&
(
(forward_node_id < numberOfNodes) ||
(reverse_node_id < numberOfNodes)
) &&
(
(forward_weight != INVALID_EDGE_WEIGHT) ||
(reverse_weight != INVALID_EDGE_WEIGHT)
) &&
(name_id != std::numeric_limits<unsigned>::max()
);
}
bool operator==(const PhantomNode & other) const
{
return location == other.location;
}
};
struct PhantomNodes {
PhantomNode startPhantom;
PhantomNode targetPhantom;
void Reset() {
startPhantom.Reset();
targetPhantom.Reset();
struct PhantomNodes
{
PhantomNode source_phantom;
PhantomNode target_phantom;
void Reset()
{
source_phantom.Reset();
target_phantom.Reset();
}
bool PhantomsAreOnSameNodeBasedEdge() const {
return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
bool PhantomsAreOnSameNodeBasedEdge() const
{
return (source_phantom.forward_node_id == target_phantom.forward_node_id);
}
bool AtLeastOnePhantomNodeIsUINTMAX() const {
return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
bool AtLeastOnePhantomNodeIsInvalid() const
{
return ((source_phantom.forward_node_id == SPECIAL_NODEID) && (source_phantom.reverse_node_id == SPECIAL_NODEID)) ||
((target_phantom.forward_node_id == SPECIAL_NODEID) && (target_phantom.reverse_node_id == SPECIAL_NODEID));
}
bool PhantomNodesHaveEqualLocation() const {
return startPhantom == targetPhantom;
bool PhantomNodesHaveEqualLocation() const
{
return source_phantom == target_phantom;
}
};
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl;
out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl;
out << "startCoord: " << pn.startPhantom.location << std::endl;
out << "targetCoord: " << pn.targetPhantom.location << std::endl;
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
{
out << "source_coord: " << pn.source_phantom.location << "\n";
out << "target_coord: " << pn.target_phantom.location << std::endl;
return out;
}
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
out << "node: " << pn.edgeBasedNode << ", name: " << pn.nodeBasedEdgeNameID << ", w1: " << pn.weight1 << ", w2: " << pn.weight2 << ", ratio: " << pn.ratio << ", loc: " << pn.location;
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn)
{
out << "node1: " << pn.forward_node_id << ", " <<
"node2: " << pn.reverse_node_id << ", " <<
"name: " << pn.name_id << ", " <<
"fwd-w: " << pn.forward_weight << ", " <<
"rev-w: " << pn.reverse_weight << ", " <<
"fwd-o: " << pn.forward_offset << ", " <<
"rev-o: " << pn.reverse_offset << ", " <<
"geom: " << pn.packed_geometry_id << ", " <<
"pos: " << pn.fwd_segment_position << ", " <<
"loc: " << pn.location;
return out;
}

View File

@ -30,8 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h"
#include <climits>
struct QueryEdge {
NodeID source;
NodeID target;

View File

@ -34,17 +34,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp>
#include <cstddef>
#include <climits>
#include <limits>
struct NodeInfo {
typedef NodeID key_type; //type of NodeID
typedef int value_type; //type of lat,lons
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
NodeInfo(int lat, int lon, NodeID id) : lat(lat), lon(lon), id(id) { }
NodeInfo()
:
lat(std::numeric_limits<int>::max()),
lon(std::numeric_limits<int>::max()),
id(std::numeric_limits<unsigned>::max())
{ }
int lat;
int lon;
NodeID id;
@ -69,17 +72,15 @@ struct NodeInfo {
switch(n) {
case 1:
return lat;
break;
// break;
case 0:
return lon;
break;
// break;
default:
BOOST_ASSERT_MSG(false, "should not happen");
return UINT_MAX;
break;
}
BOOST_ASSERT_MSG(false, "should not happen");
return UINT_MAX;
return std::numeric_limits<unsigned>::max();
}
};

View File

@ -70,10 +70,19 @@ struct RawRouteData {
unsigned checkSum;
int lengthOfShortestPath;
int lengthOfAlternativePath;
bool source_traversed_in_reverse;
bool target_traversed_in_reverse;
bool alt_source_traversed_in_reverse;
bool alt_target_traversed_in_reverse;
RawRouteData() :
checkSum(UINT_MAX),
lengthOfShortestPath(INT_MAX),
lengthOfAlternativePath(INT_MAX)
lengthOfAlternativePath(INT_MAX),
source_traversed_in_reverse(false),
target_traversed_in_reverse(false),
alt_source_traversed_in_reverse(false),
alt_target_traversed_in_reverse(false)
{ }
};

View File

@ -29,7 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define RESTRICTION_H_
#include "../typedefs.h"
#include <climits>
#include <limits>
struct TurnRestriction {
NodeID viaNode;
@ -60,8 +61,8 @@ struct TurnRestriction {
explicit TurnRestriction(NodeID viaNode) :
viaNode(viaNode),
fromNode(UINT_MAX),
toNode(UINT_MAX) {
fromNode(std::numeric_limits<unsigned>::max()),
toNode(std::numeric_limits<unsigned>::max()) {
}
explicit TurnRestriction(const bool isOnly = false) :
@ -93,9 +94,9 @@ struct InputRestrictionContainer {
explicit InputRestrictionContainer(
bool isOnly = false
) :
fromWay(UINT_MAX),
toWay(UINT_MAX),
viaNode(UINT_MAX)
fromWay(std::numeric_limits<unsigned>::max()),
toWay(std::numeric_limits<unsigned>::max()),
viaNode(std::numeric_limits<unsigned>::max())
{
restriction.flags.isOnly = isOnly;
}
@ -105,10 +106,10 @@ struct InputRestrictionContainer {
}
static InputRestrictionContainer max_value() {
return InputRestrictionContainer(
UINT_MAX,
UINT_MAX,
UINT_MAX,
UINT_MAX
std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max()
);
}
};

View File

@ -115,6 +115,8 @@ public:
std::size_t size() const { return m_size; }
bool empty() const { return 0 == size(); }
DataT & operator[](const unsigned index) {
BOOST_ASSERT_MSG(index < m_size, "invalid size");
return m_ptr[index];
@ -126,6 +128,63 @@ public:
}
};
template<>
class SharedMemoryWrapper<bool> {
private:
unsigned * m_ptr;
std::size_t m_size;
public:
SharedMemoryWrapper() :
m_ptr(NULL),
m_size(0)
{ }
SharedMemoryWrapper(unsigned * ptr, std::size_t size) :
m_ptr(ptr),
m_size(size)
{ }
void swap( SharedMemoryWrapper<bool> & other ) {
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
std::swap( m_size, other.m_size);
std::swap( m_ptr , other.m_ptr );
}
// void SetData(const DataT * ptr, const std::size_t size) {
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
// m_ptr.reset(ptr);
// m_size = size;
// }
bool at(const std::size_t index) const {
// BOOST_ASSERT_MSG(index < m_size, "invalid size");
const unsigned bucket = index / 32;
const unsigned offset = index % 32;
return m_ptr[bucket] & (1 << offset);
}
// ShMemIterator<DataT> begin() const {
// return ShMemIterator<DataT>(m_ptr);
// }
// ShMemIterator<DataT> end() const {
// return ShMemIterator<DataT>(m_ptr+m_size);
// }
std::size_t size() const { return m_size; }
bool empty() const { return 0 == size(); }
bool operator[](const unsigned index) {
BOOST_ASSERT_MSG(index < m_size, "invalid size");
const unsigned bucket = index / 32;
const unsigned offset = index % 32;
return m_ptr[bucket] & (1 << offset);
}
};
template<typename DataT, bool UseSharedMemory>
struct ShM {
typedef typename boost::conditional<
@ -135,5 +194,4 @@ struct ShM {
>::type vector;
};
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H

View File

@ -112,16 +112,18 @@ public:
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find first segment of edge (" <<
u << "," << data.id << "," << v << ")";
u << "," << data.id << "," << v << "), eid: " << eid;
data.shortcut = false;
BOOST_ASSERT(false);
}
eid2 = FindEdgeInEitherDirection(data.id, v);
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find second segment of edge (" <<
u << "," << data.id << "," << v << ")";
u << "," << data.id << "," << v << "), eid2: " << eid2;
data.shortcut = false;
BOOST_ASSERT(false);
}
}
}
@ -155,17 +157,17 @@ public:
}
EdgeIterator BeginEdges( const NodeIterator n ) const {
return EdgeIterator( _nodes[n].firstEdge );
return EdgeIterator( _nodes.at(n).firstEdge );
}
EdgeIterator EndEdges( const NodeIterator n ) const {
return EdgeIterator( _nodes[n+1].firstEdge );
return EdgeIterator( _nodes.at(n+1).firstEdge );
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
EdgeIterator smallestEdge = SPECIAL_EDGEID;
EdgeWeight smallestWeight = UINT_MAX;
EdgeWeight smallestWeight = INVALID_EDGE_WEIGHT;
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
const NodeID target = GetTarget(edge);
const EdgeWeight weight = GetEdgeData(edge).distance;

View File

@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DeallocatingVector.h"
#include "HilbertValue.h"
#include "PhantomNodes.h"
#include "QueryNode.h"
#include "SharedMemoryFactory.h"
#include "SharedMemoryVectorWrapper.h"
@ -51,6 +52,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/algorithm/minmax_element.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/type_traits.hpp>
@ -68,7 +70,7 @@ const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
template<class DataT, bool UseSharedMemory = false>
template<class DataT, class CoordinateListT = std::vector<FixedPointCoordinate>, bool UseSharedMemory = false>
class StaticRTree : boost::noncopyable {
public:
struct RectangleInt2D {
@ -82,22 +84,35 @@ public:
int32_t min_lat, max_lat;
inline void InitializeMBRectangle(
const DataT * objects,
const uint32_t element_count
DataT const * objects,
const uint32_t element_count,
const std::vector<NodeInfo> & coordinate_list
) {
for(uint32_t i = 0; i < element_count; ++i) {
min_lon = std::min(
min_lon, std::min(objects[i].lon1, objects[i].lon2)
min_lon, std::min(
coordinate_list.at(objects[i].u).lon,
coordinate_list.at(objects[i].v).lon
)
);
max_lon = std::max(
max_lon, std::max(objects[i].lon1, objects[i].lon2)
max_lon, std::max(
coordinate_list.at(objects[i].u).lon,
coordinate_list.at(objects[i].v).lon
)
);
min_lat = std::min(
min_lat, std::min(objects[i].lat1, objects[i].lat2)
min_lat, std::min(
coordinate_list.at(objects[i].u).lat,
coordinate_list.at(objects[i].v).lon
)
);
max_lat = std::max(
max_lat, std::max(objects[i].lat1, objects[i].lat2)
max_lat, std::max(
coordinate_list.at(objects[i].u).lat,
coordinate_list.at(objects[i].v).lon
)
);
}
}
@ -221,9 +236,9 @@ public:
}
inline bool Contains(const FixedPointCoordinate & location) const {
bool lats_contained =
const bool lats_contained =
(location.lat > min_lat) && (location.lat < max_lat);
bool lons_contained =
const bool lons_contained =
(location.lon > min_lon) && (location.lon < max_lon);
return lats_contained && lons_contained;
}
@ -289,21 +304,23 @@ private:
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
uint64_t m_element_count;
const std::string m_leaf_node_filename;
boost::shared_ptr<CoordinateListT> m_coordinate_list;
public:
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
explicit StaticRTree(
std::vector<DataT> & input_data_vector,
const std::string tree_node_filename,
const std::string leaf_node_filename
const std::string leaf_node_filename,
const std::vector<NodeInfo> & coordinate_list
)
: m_element_count(input_data_vector.size()),
m_leaf_node_filename(leaf_node_filename)
{
SimpleLogger().Write() <<
"constructing r-tree of " << m_element_count <<
" elements";
" edge elements build on-top of " << coordinate_list.size() << " coordinates";
double time1 = get_timestamp();
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
@ -315,8 +332,17 @@ public:
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
input_wrapper_vector[element_counter].m_array_index = element_counter;
//Get Hilbert-Value for centroid in mercartor projection
DataT & current_element = input_data_vector[element_counter];
FixedPointCoordinate current_centroid = current_element.Centroid();
DataT const & current_element = input_data_vector[element_counter];
FixedPointCoordinate current_centroid = DataT::Centroid(
FixedPointCoordinate(
coordinate_list.at(current_element.u).lat,
coordinate_list.at(current_element.u).lon
),
FixedPointCoordinate(
coordinate_list.at(current_element.v).lat,
coordinate_list.at(current_element.v).lon
)
);
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
uint64_t current_hilbert_value = get_hilbert_number(current_centroid);
@ -347,7 +373,11 @@ public:
}
//generate tree node that resemble the objects in leaf and store it for next level
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
current_node.minimum_bounding_rectangle.InitializeMBRectangle(
current_leaf.objects,
current_leaf.object_count,
coordinate_list
);
current_node.child_is_on_disk = true;
current_node.children[0] = tree_nodes_in_level.size();
tree_nodes_in_level.push_back(current_node);
@ -426,9 +456,11 @@ public:
//Read-only operation for queries
explicit StaticRTree(
const boost::filesystem::path & node_file,
const boost::filesystem::path & leaf_file
) : m_leaf_node_filename(leaf_file.string()) {
const boost::filesystem::path & leaf_file,
const boost::shared_ptr<CoordinateListT> coordinate_list
) : m_leaf_node_filename( leaf_file.string() ) {
//open tree node file and load into RAM.
m_coordinate_list = coordinate_list;
if ( !boost::filesystem::exists( node_file ) ) {
throw OSRMException("ram index file does not exist");
@ -463,9 +495,11 @@ public:
explicit StaticRTree(
TreeNode * tree_node_ptr,
const uint32_t number_of_nodes,
const boost::filesystem::path & leaf_file
const boost::filesystem::path & leaf_file,
boost::shared_ptr<CoordinateListT> coordinate_list
) : m_search_tree(tree_node_ptr, number_of_nodes),
m_leaf_node_filename(leaf_file.string())
m_leaf_node_filename(leaf_file.string()),
m_coordinate_list(coordinate_list)
{
//open leaf node file and store thread specific pointer
if ( !boost::filesystem::exists( leaf_file ) ) {
@ -487,152 +521,7 @@ public:
//SimpleLogger().Write() << m_element_count << " elements in leafs";
}
//Read-only operation for queries
/*
inline void FindKNearestPhantomNodesForCoordinate(
const FixedPointCoordinate & location,
const unsigned zoom_level,
const unsigned candidate_count,
std::vector<std::pair<PhantomNode, double> > & result_vector
) const {
bool ignore_tiny_components = (zoom_level <= 14);
DataT nearest_edge;
uint32_t io_count = 0;
uint32_t explored_tree_nodes_count = 0;
SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
double min_dist = std::numeric_limits<double>::max();
double min_max_dist = std::numeric_limits<double>::max();
bool found_a_nearest_edge = false;
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
//initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue;
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
BOOST_ASSERT_MSG(std::numberic_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
while(!traversal_queue.empty()) {
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
++explored_tree_nodes_count;
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
bool prune_upward = (current_query_node.min_dist >= min_dist);
if( !prune_downward && !prune_upward ) { //downward pruning
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
if (current_tree_node.child_is_on_disk) {
LeafNode current_leaf_node;
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
++io_count;
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
DataT & current_edge = current_leaf_node.objects[i];
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
continue;
}
double current_ratio = 0.;
double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
input_coordinate,
nearest,
current_ratio
);
if(
current_perpendicular_distance < min_dist
&& !DoubleEpsilonCompare(
current_perpendicular_distance,
min_dist
)
) { //found a new minimum
min_dist = current_perpendicular_distance;
result_phantom_node.edgeBasedNode = current_edge.id;
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
result_phantom_node.weight1 = current_edge.weight;
result_phantom_node.weight2 = INT_MAX;
result_phantom_node.location = nearest;
current_start_coordinate.lat = current_edge.lat1;
current_start_coordinate.lon = current_edge.lon1;
current_end_coordinate.lat = current_edge.lat2;
current_end_coordinate.lon = current_edge.lon2;
nearest_edge = current_edge;
found_a_nearest_edge = true;
} else if(
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
&& EdgesAreEquivalent(
current_start_coordinate,
FixedPointCoordinate(
current_edge.lat1,
current_edge.lon1
),
FixedPointCoordinate(
current_edge.lat2,
current_edge.lon2
),
current_end_coordinate
)
) {
result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode);
result_phantom_node.weight2 = current_edge.weight;
}
}
} else {
//traverse children, prune if global mindist is smaller than local one
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
const int32_t child_id = current_tree_node.children[i];
TreeNode & child_tree_node = m_search_tree[child_id];
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
if( current_min_max_dist < min_max_dist ) {
min_max_dist = current_min_max_dist;
}
if (current_min_dist > min_max_dist) {
continue;
}
if (current_min_dist > min_dist) { //upward pruning
continue;
}
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
}
}
}
}
const double distance_to_edge =
ApproximateDistance (
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
result_phantom_node.location
);
const double length_of_edge =
ApproximateDistance(
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
FixedPointCoordinate(nearest_edge.lat2, nearest_edge.lon2)
);
const double ratio = (found_a_nearest_edge ?
std::min(1., distance_to_edge/ length_of_edge ) : 0 );
result_phantom_node.weight1 *= ratio;
if(INT_MAX != result_phantom_node.weight2) {
result_phantom_node.weight2 *= (1.-ratio);
}
result_phantom_node.ratio = ratio;
//Hack to fix rounding errors and wandering via nodes.
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
result_phantom_node.location.lon = input_coordinate.lon;
}
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
result_phantom_node.location.lat = input_coordinate.lat;
}
SimpleLogger().Write() << "mindist: " << min_distphantom_node.isBidirected() ? "yes" : "no");
return found_a_nearest_edge;
}
*/
bool LocateClosestEndPointForCoordinate(
const FixedPointCoordinate & input_coordinate,
FixedPointCoordinate & result_coordinate,
@ -671,7 +560,7 @@ public:
current_leaf_node
);
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
const DataT & current_edge = current_leaf_node.objects[i];
DataT const & current_edge = current_leaf_node.objects[i];
if(
ignore_tiny_components &&
current_edge.belongsToTinyComponent
@ -682,29 +571,29 @@ public:
double current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
input_coordinate.lat,
input_coordinate.lon,
current_edge.lat1,
current_edge.lon1
m_coordinate_list->at(current_edge.u).lat,
m_coordinate_list->at(current_edge.u).lon
);
if( current_minimum_distance < min_dist ) {
//found a new minimum
min_dist = current_minimum_distance;
result_coordinate.lat = current_edge.lat1;
result_coordinate.lon = current_edge.lon1;
result_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
result_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
found_a_nearest_edge = true;
}
current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
input_coordinate.lat,
input_coordinate.lon,
current_edge.lat2,
current_edge.lon2
m_coordinate_list->at(current_edge.v).lat,
m_coordinate_list->at(current_edge.v).lon
);
if( current_minimum_distance < min_dist ) {
//found a new minimum
min_dist = current_minimum_distance;
result_coordinate.lat = current_edge.lat2;
result_coordinate.lon = current_edge.lon2;
result_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
result_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
found_a_nearest_edge = true;
}
}
@ -783,7 +672,9 @@ public:
}
double current_ratio = 0.;
double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
const double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
m_coordinate_list->at(current_edge.u),
m_coordinate_list->at(current_edge.v),
input_coordinate,
nearest,
current_ratio
@ -799,41 +690,24 @@ public:
)
) { //found a new minimum
min_dist = current_perpendicular_distance;
result_phantom_node.edgeBasedNode = current_edge.id;
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
result_phantom_node.weight1 = current_edge.weight;
result_phantom_node.weight2 = INT_MAX;
//TODO: use assignment c'tor in PhantomNode
result_phantom_node.forward_node_id = current_edge.forward_edge_based_node_id;
result_phantom_node.reverse_node_id = current_edge.reverse_edge_based_node_id;
result_phantom_node.name_id = current_edge.name_id;
result_phantom_node.forward_weight = current_edge.forward_weight;
result_phantom_node.reverse_weight = current_edge.reverse_weight;
result_phantom_node.forward_offset = current_edge.forward_offset;
result_phantom_node.reverse_offset = current_edge.reverse_offset;
result_phantom_node.packed_geometry_id = current_edge.packed_geometry_id;
result_phantom_node.fwd_segment_position = current_edge.fwd_segment_position;
result_phantom_node.location = nearest;
current_start_coordinate.lat = current_edge.lat1;
current_start_coordinate.lon = current_edge.lon1;
current_end_coordinate.lat = current_edge.lat2;
current_end_coordinate.lon = current_edge.lon2;
current_start_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
current_start_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
current_end_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
current_end_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
nearest_edge = current_edge;
found_a_nearest_edge = true;
} else
if( DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
( 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) ) &&
EdgesAreEquivalent(
current_start_coordinate,
FixedPointCoordinate(
current_edge.lat1,
current_edge.lon1
),
FixedPointCoordinate(
current_edge.lat2,
current_edge.lon2
),
current_end_coordinate
)
) {
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
result_phantom_node.weight2 = current_edge.weight;
if(current_edge.id < result_phantom_node.edgeBasedNode) {
result_phantom_node.edgeBasedNode = current_edge.id;
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
std::swap(current_end_coordinate, current_start_coordinate);
}
}
}
} else {
@ -884,11 +758,28 @@ public:
ratio = std::min(1., ratio);
}
result_phantom_node.weight1 *= ratio;
if(INT_MAX != result_phantom_node.weight2) {
result_phantom_node.weight2 *= (1.-ratio);
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_offset: " << result_phantom_node.forward_offset;
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_offset: " << result_phantom_node.reverse_offset;
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_weight: " << result_phantom_node.forward_weight;
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_weight: " << result_phantom_node.reverse_weight;
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
{
result_phantom_node.forward_weight *= ratio;
}
result_phantom_node.ratio = ratio;
if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
{
result_phantom_node.reverse_weight *= (1.-ratio);
}
// SimpleLogger().Write(logDEBUG) << "[rtree] result location: " << result_phantom_node.location << ", start: " << current_start_coordinate << ", end: " << current_end_coordinate;
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd node: " << result_phantom_node.forward_node_id << ", rev node: " << result_phantom_node.reverse_node_id;
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd weight: " << result_phantom_node.forward_weight << ", rev weight: " << result_phantom_node.reverse_weight;
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd offset: " << result_phantom_node.forward_offset << ", rev offset: " << result_phantom_node.reverse_offset;
// SimpleLogger().Write(logDEBUG) << "[rtree] bidirected: " << (result_phantom_node.isBidirected() ? "y" : "n");
// SimpleLogger().Write(logDEBUG) << "[rtree] name id: " << result_phantom_node.name_id;
// SimpleLogger().Write(logDEBUG) << "[rtree] geom id: " << result_phantom_node.packed_geometry_id;
// SimpleLogger().Write(logDEBUG) << "[rtree] ratio: " << ratio;
return found_a_nearest_edge;
}

View File

@ -92,6 +92,4 @@ struct TurnInstructionsClass : boost::noncopyable {
};
static TurnInstructionsClass TurnInstructions;
#endif /* TURNINSTRUCTIONS_H_ */

View File

@ -31,18 +31,18 @@ DescriptionFactory::DescriptionFactory() : entireLength(0) { }
DescriptionFactory::~DescriptionFactory() { }
inline double DescriptionFactory::DegreeToRadian(const double degree) const {
return degree * (M_PI/180);
inline double DescriptionFactory::DegreeToRadian(const double degree) const
{
return degree * (M_PI/180.);
}
inline double DescriptionFactory::RadianToDegree(const double radian) const {
return radian * (180/M_PI);
inline double DescriptionFactory::RadianToDegree(const double radian) const
{
return radian * (180./M_PI);
}
double DescriptionFactory::GetBearing(
const FixedPointCoordinate & A,
const FixedPointCoordinate & B
) const {
double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const FixedPointCoordinate & B) const
{
double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
@ -51,55 +51,52 @@ double DescriptionFactory::GetBearing(
const double y = sin(delta_long) * cos(lat2);
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
double result = RadianToDegree(atan2(y, x));
while(result < 0.) {
while (result < 0.)
{
result += 360.;
}
while(result >= 360.) {
while (result >= 360.)
{
result -= 360.;
}
return result;
}
void DescriptionFactory::SetStartSegment(const PhantomNode & start) {
start_phantom = start;
void DescriptionFactory::SetStartSegment(const PhantomNode & source, const bool source_traversed_in_reverse)
{
start_phantom = source;
AppendSegment(
start.location,
PathData(0, start.nodeBasedEdgeNameID, 10, start.weight1)
source.location,
PathData(0, source.name_id, 10, source.forward_weight)
);
}
void DescriptionFactory::SetEndSegment(const PhantomNode & target) {
void DescriptionFactory::SetEndSegment(const PhantomNode & target, const bool target_traversed_in_reverse)
{
target_phantom = target;
pathDescription.push_back(
SegmentInformation(
target.location,
target.nodeBasedEdgeNameID,
target.name_id,
0,
target.weight1,
target.reverse_weight,
0,
true
)
);
}
void DescriptionFactory::AppendSegment(
const FixedPointCoordinate & coordinate,
const PathData & data
) {
if(
( 1 == pathDescription.size()) &&
( pathDescription.back().location == coordinate)
) {
pathDescription.back().name_id = data.name_id;
} else {
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const PathData & path_point)
{
if ((1 == pathDescription.size()) && ( pathDescription.back().location == coordinate))
{
pathDescription.back().name_id = path_point.name_id;
}
else
{
pathDescription.push_back(
SegmentInformation(
coordinate,
data.name_id,
data.durationOfSegment,
0,
data.turnInstruction
)
SegmentInformation(coordinate, path_point.name_id, path_point.durationOfSegment, 0, path_point.turnInstruction)
);
}
}
@ -137,7 +134,7 @@ void DescriptionFactory::BuildRouteSummary(
const double distance,
const unsigned time
) {
summary.startName = start_phantom.nodeBasedEdgeNameID;
summary.destName = target_phantom.nodeBasedEdgeNameID;
summary.startName = start_phantom.name_id;
summary.destName = target_phantom.name_id;
summary.BuildDurationAndLengthStrings(distance, time);
}

View File

@ -71,7 +71,7 @@ public:
) {
//compute distance/duration for route summary
intToString(round(distance), lengthString);
int travel_time = time/10;
int travel_time = round(time/10.);
intToString(std::max(travel_time, 1), durationString);
}
} summary;
@ -87,8 +87,8 @@ public:
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data);
void BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode & start_phantom);
void SetEndSegment(const PhantomNode & start_phantom);
void SetStartSegment(const PhantomNode & start_phantom, const bool source_traversed_in_reverse);
void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse);
void AppendEncodedPolylineString(
const bool return_encoded,
std::vector<std::string> & output
@ -105,14 +105,13 @@ public:
/** starts at index 1 */
pathDescription[0].length = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
for (unsigned i = 1; i < pathDescription.size(); ++i)
{
//move down names by one, q&d hack
pathDescription[i-1].name_id = pathDescription[i].name_id;
pathDescription[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
}
// std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].name_id);
// std::string string1;
/*Simplify turn instructions
Input :
10. Turn left on B 36 for 20 km
@ -154,23 +153,23 @@ public:
// string0 = string1;
// }
double lengthOfSegment = 0;
unsigned durationOfSegment = 0;
unsigned indexOfSegmentBegin = 0;
double segment_length = 0.;
unsigned segment_duration = 0;
unsigned segment_start_index = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
entireLength += pathDescription[i].length;
lengthOfSegment += pathDescription[i].length;
durationOfSegment += pathDescription[i].duration;
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
segment_length += pathDescription[i].length;
segment_duration += pathDescription[i].duration;
pathDescription[segment_start_index].length = segment_length;
pathDescription[segment_start_index].duration = segment_duration;
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
BOOST_ASSERT(pathDescription[i].necessary);
lengthOfSegment = 0;
durationOfSegment = 0;
indexOfSegmentBegin = i;
segment_length = 0;
segment_duration = 0;
segment_start_index = i;
}
}
@ -179,21 +178,17 @@ public:
if(pathDescription.size() > 2){
pathDescription.pop_back();
pathDescription.back().necessary = true;
pathDescription.back().turn_instruction = TurnInstructions.NoTurn;
target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->name_id;
pathDescription.back().turn_instruction = TurnInstructionsClass::NoTurn;
target_phantom.name_id = (pathDescription.end()-2)->name_id;
}
} else {
pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
}
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
if(pathDescription.size() > 2) {
pathDescription.erase(pathDescription.begin());
pathDescription[0].turn_instruction = TurnInstructions.HeadOn;
pathDescription[0].turn_instruction = TurnInstructionsClass::HeadOn;
pathDescription[0].necessary = true;
start_phantom.nodeBasedEdgeNameID = pathDescription[0].name_id;
start_phantom.name_id = pathDescription[0].name_id;
}
} else {
pathDescription[0].duration *= start_phantom.ratio;
}
//Generalize poly line

View File

@ -65,12 +65,12 @@ public:
(raw_route.unpacked_path_segments[0].size());
if( found_route ) {
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.startPhantom.location.lat,
phantom_node_list.source_phantom.location.lat,
tmp
);
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.startPhantom.location.lon,
phantom_node_list.source_phantom.location.lon,
tmp
);
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
@ -90,12 +90,12 @@ public:
}
// Add the via point or the end coordinate
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.targetPhantom.location.lat,
phantom_node_list.target_phantom.location.lat,
tmp
);
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.targetPhantom.location.lon,
phantom_node_list.target_phantom.location.lon,
tmp
);
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");

View File

@ -44,6 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
template<class DataFacadeT>
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
private:
// TODO: initalize in c'tor
DataFacadeT * facade;
DescriptorConfig config;
DescriptionFactory description_factory;
@ -59,7 +60,7 @@ private:
int start_index;
int name_id;
int leave_at_exit;
} roundAbout;
} round_about;
struct Segment {
Segment() : name_id(-1), length(-1), position(-1) {}
@ -90,7 +91,7 @@ public:
void SetConfig(const DescriptorConfig & c) { config = c; }
int DescribeLeg(
const std::vector<PathData> & route_leg,
const std::vector<PathData> route_leg,
const PhantomNodes & leg_phantoms
) {
int added_element_count = 0;
@ -98,10 +99,10 @@ public:
FixedPointCoordinate current_coordinate;
BOOST_FOREACH(const PathData & path_data, route_leg) {
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
description_factory.AppendSegment(current_coordinate, path_data );
description_factory.AppendSegment(current_coordinate, path_data);
++added_element_count;
}
// description_factory.SetEndSegment( leg_phantoms.targetPhantom );
// description_factory.SetEndSegment( leg_phantoms.target_phantom );
++added_element_count;
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count );
return added_element_count;
@ -119,7 +120,8 @@ public:
"{\"status\":"
);
if(INT_MAX == raw_route.lengthOfShortestPath) {
if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath)
{
//We do not need to do much, if there is no route ;-)
reply.content.push_back(
"207,\"status_message\": \"Cannot find route between points\"}"
@ -127,12 +129,36 @@ public:
return;
}
description_factory.SetStartSegment(phantom_nodes.startPhantom);
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath;
//check if first segment is non-zero
std::string road_name;
road_name = facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
// for each unpacked segment add the leg to the description
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
{
const std::vector<PathData> & leg_path = raw_route.unpacked_path_segments[i];
FixedPointCoordinate current_coordinate;
BOOST_FOREACH(const PathData & path_data, leg_path)
{
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
road_name = facade->GetEscapedNameForNameID(path_data.name_id);
}
}
//check if last segment is non-zero
road_name = facade->GetEscapedNameForNameID(phantom_nodes.target_phantom.name_id);
description_factory.SetStartSegment(phantom_nodes.source_phantom, raw_route.source_traversed_in_reverse);
reply.content.push_back("0,"
"\"status_message\": \"Found route between points\",");
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
for( unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i ) {
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
{
const int added_segments = DescribeLeg(
raw_route.unpacked_path_segments[i],
raw_route.segmentEndCoordinates[i]
@ -142,7 +168,7 @@ public:
added_segments + shortest_leg_end_indices.back()
);
}
description_factory.SetEndSegment(phantom_nodes.targetPhantom);
description_factory.SetEndSegment(phantom_nodes.target_phantom, raw_route.target_traversed_in_reverse);
description_factory.Run(facade, config.zoom_level);
reply.content.push_back("\"route_geometry\": ");
@ -194,14 +220,15 @@ public:
//only one alternative route is computed at this time, so this is hardcoded
if(raw_route.lengthOfAlternativePath != INT_MAX) {
alternate_descriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT)
{
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse);
//Get all the coordinates for the computed route
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) {
current = facade->GetCoordinateOfNode(path_data.node);
alternate_descriptionFactory.AppendSegment(current, path_data );
}
alternate_descriptionFactory.SetEndSegment(phantom_nodes.targetPhantom);
alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom, raw_route.alt_target_traversed_in_reverse);
}
alternate_descriptionFactory.Run(facade, config.zoom_level);
@ -286,7 +313,7 @@ public:
std::string tmp;
FixedPointCoordinate::convertInternalReversedCoordinateToString(
raw_route.segmentEndCoordinates.front().startPhantom.location,
raw_route.segmentEndCoordinates.front().source_phantom.location,
tmp
);
reply.content.push_back("[");
@ -296,7 +323,7 @@ public:
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) {
tmp.clear();
FixedPointCoordinate::convertInternalReversedCoordinateToString(
nodes.targetPhantom.location,
nodes.target_phantom.location,
tmp
);
reply.content.push_back(",[");
@ -332,11 +359,11 @@ public:
std::string hint;
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) {
reply.content.push_back("\"");
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].startPhantom, hint);
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].source_phantom, hint);
reply.content.push_back(hint);
reply.content.push_back("\", ");
}
EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().targetPhantom, hint);
EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().target_phantom, hint);
reply.content.push_back("\"");
reply.content.push_back(hint);
reply.content.push_back("\"]");
@ -419,56 +446,61 @@ public:
//Segment information has following format:
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
unsigned prefixSumOfNecessarySegments = 0;
roundAbout.leave_at_exit = 0;
roundAbout.name_id = 0;
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
unsigned necessary_segments_running_index = 0;
round_about.leave_at_exit = 0;
round_about.name_id = 0;
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
//Fetch data from Factory and generate a string from it.
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
TurnInstruction current_instruction = segment.turn_instruction & TurnInstructions.InverseAccessRestrictionFlag;
TurnInstruction current_instruction = segment.turn_instruction & TurnInstructionsClass::InverseAccessRestrictionFlag;
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
if(TurnInstructions.TurnIsNecessary( current_instruction) ) {
if(TurnInstructions.EnterRoundAbout == current_instruction) {
roundAbout.name_id = segment.name_id;
roundAbout.start_index = prefixSumOfNecessarySegments;
} else {
if(0 != prefixSumOfNecessarySegments){
if (TurnInstructionsClass::TurnIsNecessary( current_instruction) )
{
if (TurnInstructionsClass::EnterRoundAbout == current_instruction)
{
round_about.name_id = segment.name_id;
round_about.start_index = necessary_segments_running_index;
}
else
{
if (0 != necessary_segments_running_index)
{
reply.content.push_back(",");
}
reply.content.push_back("[\"");
if(TurnInstructions.LeaveRoundAbout == current_instruction) {
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
reply.content.push_back(tmpInstruction);
if(TurnInstructionsClass::LeaveRoundAbout == current_instruction) {
intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction);
reply.content.push_back(temp_instruction);
reply.content.push_back("-");
intToString(roundAbout.leave_at_exit+1, tmpInstruction);
reply.content.push_back(tmpInstruction);
roundAbout.leave_at_exit = 0;
intToString(round_about.leave_at_exit+1, temp_instruction);
reply.content.push_back(temp_instruction);
round_about.leave_at_exit = 0;
} else {
intToString(current_instruction, tmpInstruction);
reply.content.push_back(tmpInstruction);
intToString(current_instruction, temp_instruction);
reply.content.push_back(temp_instruction);
}
reply.content.push_back("\",\"");
reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id));
reply.content.push_back("\",");
intToString(segment.length, tmpDist);
reply.content.push_back(tmpDist);
intToString(segment.length, temp_dist);
reply.content.push_back(temp_dist);
reply.content.push_back(",");
intToString(prefixSumOfNecessarySegments, tmpLength);
reply.content.push_back(tmpLength);
intToString(necessary_segments_running_index, temp_length);
reply.content.push_back(temp_length);
reply.content.push_back(",");
intToString(segment.duration/10, tmpDuration);
reply.content.push_back(tmpDuration);
intToString(round(segment.duration/10.), temp_duration);
reply.content.push_back(temp_duration);
reply.content.push_back(",\"");
intToString(segment.length, tmpLength);
reply.content.push_back(tmpLength);
intToString(segment.length, temp_length);
reply.content.push_back(temp_length);
reply.content.push_back("m\",\"");
double bearing_value = round(segment.bearing/10.);
reply.content.push_back(Azimuth::Get(bearing_value));
reply.content.push_back("\",");
intToString(bearing_value, tmpBearing);
reply.content.push_back(tmpBearing);
intToString(bearing_value, temp_bearing);
reply.content.push_back(temp_bearing);
reply.content.push_back("]");
route_segments_list.push_back(
@ -479,22 +511,22 @@ public:
)
);
}
} else if(TurnInstructions.StayOnRoundAbout == current_instruction) {
++roundAbout.leave_at_exit;
} else if(TurnInstructionsClass::StayOnRoundAbout == current_instruction) {
++round_about.leave_at_exit;
}
if(segment.necessary)
++prefixSumOfNecessarySegments;
++necessary_segments_running_index;
}
if(INT_MAX != route_length) {
reply.content.push_back(",[\"");
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
reply.content.push_back(tmpInstruction);
intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction);
reply.content.push_back(temp_instruction);
reply.content.push_back("\",\"");
reply.content.push_back("\",");
reply.content.push_back("0");
reply.content.push_back(",");
intToString(prefixSumOfNecessarySegments-1, tmpLength);
reply.content.push_back(tmpLength);
intToString(necessary_segments_running_index-1, temp_length);
reply.content.push_back(temp_length);
reply.content.push_back(",");
reply.content.push_back("0");
reply.content.push_back(",\"");

View File

@ -362,7 +362,6 @@ void ExtractionContainers::PrepareData(
break;
default:
throw OSRMException("edge has broken direction");
break;
}
file_out_stream.write(
(char*)&integer_weight, sizeof(int)
@ -373,23 +372,27 @@ void ExtractionContainers::PrepareData(
sizeof(short)
);
file_out_stream.write(
(char*)&edge_iterator->nameID,
(char *) &edge_iterator->nameID,
sizeof(unsigned)
);
file_out_stream.write(
(char*)&edge_iterator->isRoundabout,
(char *) &edge_iterator->isRoundabout,
sizeof(bool)
);
file_out_stream.write(
(char*)&edge_iterator->ignoreInGrid,
(char *) &edge_iterator->ignoreInGrid,
sizeof(bool)
);
file_out_stream.write(
(char*)&edge_iterator->isAccessRestricted,
(char *) &edge_iterator->isAccessRestricted,
sizeof(bool)
);
file_out_stream.write(
(char*)&edge_iterator->isContraFlow,
(char *) &edge_iterator->isContraFlow,
sizeof(bool)
);
file_out_stream.write(
(char *) &edge_iterator->is_split,
sizeof(bool)
);
++number_of_used_edges;

View File

@ -75,13 +75,13 @@ inline unsigned parseDuration(const std::string &s) {
return UINT_MAX;
}
inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
boost::algorithm::to_lower(input);
int n = stringToInt(input);
if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
n = (n*1609)/1000;
}
return n;
}
// inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
// boost::algorithm::to_lower(input);
// int n = stringToInt(input);
// if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
// n = (n*1609)/1000;
// }
// return n;
// }
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */

View File

@ -28,34 +28,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ExtractorCallbacks.h"
#include "ExtractionContainers.h"
#include "ExtractionHelperFunctions.h"
#include "ExtractionWay.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/ImportNode.h"
#include "../Util/SimpleLogger.h"
#include <osrm/Coordinate.h>
#include <cfloat>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
#include <string>
#include <vector>
ExtractorCallbacks::ExtractorCallbacks()
:
stringMap(NULL),
string_map(NULL),
externalMemory(NULL)
{ }
ExtractorCallbacks::ExtractorCallbacks(
ExtractionContainers * ext,
StringMap * strMap
boost::unordered_map<std::string, NodeID> * string_map
) :
stringMap(strMap),
string_map(string_map),
externalMemory(ext)
{ }
@ -95,11 +89,11 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
}
//Get the unique identifier for the street name
const StringMap::const_iterator & string_map_iterator = stringMap->find(parsed_way.name);
if(stringMap->end() == string_map_iterator) {
const boost::unordered_map<std::string, NodeID>::const_iterator & string_map_iterator = string_map->find(parsed_way.name);
if(string_map->end() == string_map_iterator) {
parsed_way.nameID = externalMemory->name_list.size();
externalMemory->name_list.push_back(parsed_way.name);
stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
string_map->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
} else {
parsed_way.nameID = string_map_iterator->second;
}
@ -113,16 +107,19 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
externalMemory->all_edges_list.push_back(
InternalExtractorEdge(parsed_way.path[n],
parsed_way.path[n+1],
parsed_way.type,
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
parsed_way.speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted
InternalExtractorEdge(
parsed_way.path[n],
parsed_way.path[n+1],
parsed_way.type,
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
parsed_way.speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
false,
split_bidirectional_edge
)
);
externalMemory->used_node_id_list.push_back(parsed_way.path[n]);
@ -136,17 +133,19 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
externalMemory->all_edges_list.push_back(
InternalExtractorEdge(parsed_way.path[n],
parsed_way.path[n+1],
parsed_way.type,
ExtractionWay::oneway,
parsed_way.backward_speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
(ExtractionWay::oneway == parsed_way.direction)
InternalExtractorEdge(
parsed_way.path[n],
parsed_way.path[n+1],
parsed_way.type,
ExtractionWay::oneway,
parsed_way.backward_speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
(ExtractionWay::oneway == parsed_way.direction),
split_bidirectional_edge
)
);
}

View File

@ -28,29 +28,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef EXTRACTORCALLBACKS_H_
#define EXTRACTORCALLBACKS_H_
#include "ExtractorStructs.h"
#include "../typedefs.h"
#include <boost/unordered_map.hpp>
#include <string>
struct ExternalMemoryNode;
class ExtractionContainers;
struct ExtractionWay;
struct InputRestrictionContainer;
typedef boost::unordered_map<std::string, NodeID> StringMap;
class ExtractorCallbacks{
private:
StringMap * stringMap;
boost::unordered_map<std::string, NodeID> * string_map;
ExtractionContainers * externalMemory;
ExtractorCallbacks();
public:
explicit ExtractorCallbacks(
ExtractionContainers * ext,
StringMap * strMap
boost::unordered_map<std::string, NodeID> * string_map
);
~ExtractorCallbacks();

View File

@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INTERNAL_EXTRACTOR_EDGE_H
#define INTERNAL_EXTRACTOR_EDGE_H
#include <osrm/Coordinate.h>
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
@ -47,70 +47,10 @@ struct InternalExtractorEdge {
ignoreInGrid(false),
isDurationSet(false),
isAccessRestricted(false),
isContraFlow(false)
isContraFlow(false),
is_split(false)
{ }
explicit InternalExtractorEdge(NodeID start, NodeID target)
:
start(start),
target(target),
type(0),
direction(0),
speed(0),
nameID(0),
isRoundabout(false),
ignoreInGrid(false),
isDurationSet(false),
isAccessRestricted(false),
isContraFlow(false)
{ }
explicit InternalExtractorEdge(
NodeID start,
NodeID target,
short type,
short d,
double speed
) :
start(start),
target(target),
type(type),
direction(d),
speed(speed),
nameID(0),
isRoundabout(false),
ignoreInGrid(false),
isDurationSet(false),
isAccessRestricted(false),
isContraFlow(false)
{ }
explicit InternalExtractorEdge(
NodeID start,
NodeID target,
short type,
short direction,
double speed,
unsigned nameID,
bool isRoundabout,
bool ignoreInGrid,
bool isDurationSet,
bool isAccressRestricted
) :
start(start),
target(target),
type(type),
direction(direction),
speed(speed),
nameID(nameID),
isRoundabout(isRoundabout),
ignoreInGrid(ignoreInGrid),
isDurationSet(isDurationSet),
isAccessRestricted(isAccressRestricted),
isContraFlow(false)
{
BOOST_ASSERT(0 <= type);
}
explicit InternalExtractorEdge(
NodeID start,
@ -123,7 +63,8 @@ struct InternalExtractorEdge {
bool ignoreInGrid,
bool isDurationSet,
bool isAccressRestricted,
bool isContraFlow
bool isContraFlow,
bool is_split
) :
start(start),
target(target),
@ -135,19 +76,43 @@ struct InternalExtractorEdge {
ignoreInGrid(ignoreInGrid),
isDurationSet(isDurationSet),
isAccessRestricted(isAccressRestricted),
isContraFlow(isContraFlow)
isContraFlow(isContraFlow),
is_split(is_split)
{
BOOST_ASSERT(0 <= type);
}
// necessary static util functions for stxxl's sorting
static InternalExtractorEdge min_value() {
return InternalExtractorEdge(0,0);
return InternalExtractorEdge(
0,
0,
0,
0,
0,
0,
false,
false,
false,
false,
false,
false
);
}
static InternalExtractorEdge max_value() {
return InternalExtractorEdge(
std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max()
std::numeric_limits<unsigned>::max(),
0,
0,
0,
0,
false,
false,
false,
false,
false,
false
);
}
@ -162,6 +127,7 @@ struct InternalExtractorEdge {
bool isDurationSet;
bool isAccessRestricted;
bool isContraFlow;
bool is_split;
FixedPointCoordinate startCoord;
FixedPointCoordinate targetCoord;

View File

@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ScriptingEnvironment.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/Restriction.h"
#include "../Util/MachineInfo.h"
#include "../Util/OpenMPWrapper.h"

View File

@ -76,13 +76,13 @@ public:
private:
inline void ReadData();
inline void ParseData();
inline void parseDenseNode (_ThreadData * threadData);
inline void parseNode (_ThreadData * threadData);
inline void parseRelation (_ThreadData * threadData);
inline void parseWay (_ThreadData * threadData);
inline void parseDenseNode (_ThreadData * threadData);
inline void parseNode (_ThreadData * threadData);
inline void parseRelation (_ThreadData * threadData);
inline void parseWay (_ThreadData * threadData);
inline void loadGroup (_ThreadData * threadData);
inline void loadBlock (_ThreadData * threadData);
inline void loadGroup (_ThreadData * threadData);
inline void loadBlock (_ThreadData * threadData);
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData);
inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData);

View File

@ -58,7 +58,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
// Add our function to the state's global scope
luabind::module(myLuaState) [
luabind::def("print", LUA_print<std::string>),
luabind::def("parseMaxspeed", parseMaxspeed),
// luabind::def("parseMaxspeed", parseMaxspeed),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
];

View File

@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "XMLParser.h"
#include "ExtractionWay.h"
#include "ExtractorCallbacks.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/InputReaderFactory.h"

View File

@ -33,13 +33,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <libxml/xmlreader.h>
class XMLParser : public BaseParser {
public:
XMLParser(
const char* filename,
ExtractorCallbacks* ec,
ScriptingEnvironment& se
ExtractorCallbacks * ec,
ScriptingEnvironment & se
);
bool ReadHeader();
bool Parse();

View File

@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef FIXED_POINT_COORDINATE_H_
#define FIXED_POINT_COORDINATE_H_
#include <iostream>
#include <iosfwd> //for std::ostream
static const double COORDINATE_PRECISION = 1000000.;
@ -37,7 +37,7 @@ struct FixedPointCoordinate {
int lon;
FixedPointCoordinate();
explicit FixedPointCoordinate (int lat, int lon);
explicit FixedPointCoordinate( int lat, int lon);
void Reset();
bool isSet() const;
bool isValid() const;
@ -74,11 +74,13 @@ struct FixedPointCoordinate {
const FixedPointCoordinate & coord,
std::string & output
);
void Output(std::ostream & out) const;
};
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){
out << "(" << c.lat << "," << c.lon << ")";
return out;
inline std::ostream& operator<<(std::ostream& o, FixedPointCoordinate const & c){
c.Output(o);
return o;
}
#endif /* FIXED_POINT_COORDINATE_H_ */

View File

@ -28,8 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OSRM_H
#define OSRM_H
#include <boost/scoped_ptr.hpp>
#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>
#include <osrm/ServerPaths.h>

View File

@ -50,10 +50,9 @@ public:
descriptorTable.emplace("json", 1);
}
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(
const RouteParameters & routeParameters,
http::Reply& reply
http::Reply & reply
) {
//check number of parameters
if(!routeParameters.coordinates.size()) {
@ -82,13 +81,13 @@ public:
reply.status = http::Reply::ok;
reply.content.push_back("{\"status\":");
if(UINT_MAX != result.edgeBasedNode) {
if(UINT_MAX != result.forward_node_id) {
reply.content.push_back("0,");
} else {
reply.content.push_back("207,");
}
reply.content.push_back("\"mapped_coordinate\":[");
if(UINT_MAX != result.edgeBasedNode) {
if(UINT_MAX != result.forward_node_id) {
FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
reply.content.push_back(temp_string);
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
@ -96,8 +95,8 @@ public:
reply.content.push_back(temp_string);
}
reply.content.push_back("],\"name\":\"");
if(UINT_MAX != result.edgeBasedNode) {
facade->GetName(result.nodeBasedEdgeNameID, temp_string);
if(UINT_MAX != result.forward_node_id) {
facade->GetName(result.name_id, temp_string);
reply.content.push_back(temp_string);
}
reply.content.push_back("\"}");

View File

@ -95,14 +95,11 @@ public:
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
continue;
}
}
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
facade->FindPhantomNodeForCoordinate(
rawRoute.rawViaNodeCoordinates[i],
phantomNodeVector[i],
@ -112,8 +109,8 @@ public:
PhantomNodes segmentPhantomNodes;
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
segmentPhantomNodes.source_phantom = phantomNodeVector[i];
segmentPhantomNodes.target_phantom = phantomNodeVector[i+1];
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
}
@ -132,9 +129,9 @@ public:
);
}
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
SimpleLogger().Write(logDEBUG) <<
"Error occurred, single path not found";
if (INT_MAX == rawRoute.lengthOfShortestPath)
{
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
}
reply.status = http::Reply::ok;
@ -172,11 +169,12 @@ public:
}
PhantomNodes phantomNodes;
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
phantomNodes.source_phantom = rawRoute.segmentEndCoordinates[0].source_phantom;
phantomNodes.target_phantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].target_phantom;
desc->SetConfig(descriptorConfig);
desc->Run(rawRoute, phantomNodes, facade, reply);
if("" != routeParameters.jsonpParameter) {
reply.content.push_back(")\n");
}

File diff suppressed because it is too large Load Diff

View File

@ -30,14 +30,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SearchEngineData.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/ContainerUtils.h"
#include "../Util/SimpleLogger.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/noncopyable.hpp>
#include <climits>
#include <stack>
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
@ -62,57 +62,58 @@ public:
SearchEngineData::QueryHeap & reverse_heap,
NodeID * middle_node_id,
int * upper_bound,
const int edge_expansion_offset,
const bool forward_direction
) const {
) const
{
const NodeID node = forward_heap.DeleteMin();
const int distance = forward_heap.GetKey(node);
//SimpleLogger().Write() << "Settled (" << forward_heap.GetData( node ).parent << "," << node << ")=" << distance;
if(reverse_heap.WasInserted(node) ){
if (reverse_heap.WasInserted(node))
{
const int new_distance = reverse_heap.GetKey(node) + distance;
if(new_distance < *upper_bound ){
if( new_distance >= 0 ) {
if(new_distance < *upper_bound )
{
if (new_distance >= 0)
{
*middle_node_id = node;
*upper_bound = new_distance;
}
}
}
if( (distance-edge_expansion_offset) > *upper_bound ){
if (distance > *upper_bound)
{
forward_heap.DeleteAll();
return;
}
//Stalling
for(
EdgeID edge = facade->BeginEdges( node );
edge < facade->EndEdges(node);
++edge
) {
for (EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); ++edge)
{
const EdgeData & data = facade->GetEdgeData(edge);
const bool reverse_flag = (!forward_direction) ? data.forward : data.backward;
if( reverse_flag ) {
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
if (reverse_flag)
{
const NodeID to = facade->GetTarget(edge);
const int edge_weight = data.distance;
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
if(forward_heap.WasInserted( to )) {
if(forward_heap.GetKey( to ) + edge_weight < distance) {
if (forward_heap.WasInserted(to))
{
if(forward_heap.GetKey( to ) + edge_weight < distance)
{
return;
}
}
}
}
for(
EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node);
edge < end_edge;
++edge
) {
for (EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); edge < end_edge; ++edge)
{
const EdgeData & data = facade->GetEdgeData(edge);
bool forward_directionFlag = (forward_direction ? data.forward : data.backward );
if( forward_directionFlag ) {
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
if (forward_directionFlag)
{
const NodeID to = facade->GetTarget(edge);
const int edge_weight = data.distance;
@ -126,18 +127,19 @@ public:
}
//Found a shorter Path -> Update distance
else if ( to_distance < forward_heap.GetKey( to ) ) {
//new parent
forward_heap.GetData( to ).parent = node;
forward_heap.DecreaseKey( to, to_distance );
//new parent
}
}
}
}
inline void UnpackPath(
const std::vector<NodeID> & packed_path,
std::vector<PathData> & unpacked_path
) const {
inline void UnpackPath(const std::vector<NodeID> & packed_path, const PhantomNodes & phantom_node_pair, std::vector<PathData> & unpacked_path) const
{
const bool start_traversed_in_reverse = (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
const bool target_traversed_in_reverse = (packed_path.back() != phantom_node_pair.target_phantom.forward_node_id);
const unsigned packed_path_size = packed_path.size();
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
@ -149,87 +151,170 @@ public:
}
std::pair<NodeID, NodeID> edge;
while(!recursion_stack.empty()) {
while (!recursion_stack.empty())
{
edge = recursion_stack.top();
recursion_stack.pop();
// facade->FindEdge does not suffice here in case of shortcuts.
// The above explanation unclear? Think!
EdgeID smaller_edge_id = SPECIAL_EDGEID;
int edge_weight = INT_MAX;
for(
EdgeID edge_id = facade->BeginEdges(edge.first);
edge_id < facade->EndEdges(edge.first);
++edge_id
){
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
{
const int weight = facade->GetEdgeData(edge_id).distance;
if(
(facade->GetTarget(edge_id) == edge.second) &&
if ((facade->GetTarget(edge_id) == edge.second) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).forward
){
facade->GetEdgeData(edge_id).forward)
{
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
if( SPECIAL_EDGEID == smaller_edge_id ){
for(
EdgeID edge_id = facade->BeginEdges(edge.second);
edge_id < facade->EndEdges(edge.second);
++edge_id
){
if (SPECIAL_EDGEID == smaller_edge_id)
{
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
{
const int weight = facade->GetEdgeData(edge_id).distance;
if(
(facade->GetTarget(edge_id) == edge.first) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).backward
){
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
{
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
}
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge id invalid");
BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid");
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
if( ed.shortcut ) {//unpack
const EdgeData & ed = facade->GetEdgeData(smaller_edge_id);
if (ed.shortcut)
{//unpack
const NodeID middle_node_id = ed.id;
//again, we need to this in reversed order
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
} else {
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be a shortcut");
}
else
{
BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id);
if (!facade->EdgeIsCompressed(ed.id))
{
BOOST_ASSERT( !facade->EdgeIsCompressed(ed.id) );
unpacked_path.push_back(
PathData(
facade->GetGeometryIndexForEdgeID(ed.id),
name_index,
turn_instruction,
ed.distance
)
);
}
else
{
std::vector<unsigned> id_vector;
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id), id_vector);
const int start_index = ( unpacked_path.empty() ? ( ( start_traversed_in_reverse ) ? id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1 : phantom_node_pair.source_phantom.fwd_segment_position ) : 0 );
const int end_index = id_vector.size();
BOOST_ASSERT(start_index >= 0);
BOOST_ASSERT(start_index <= end_index);
for (int i = start_index; i < end_index; ++i)
{
unpacked_path.push_back(
PathData(
id_vector[i],
name_index,
TurnInstructionsClass::NoTurn,
0
)
);
}
unpacked_path.back().turnInstruction = turn_instruction;
unpacked_path.back().durationOfSegment = ed.distance;
}
}
}
if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
{
std::vector<unsigned> id_vector;
facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id, id_vector);
if (target_traversed_in_reverse)
{
std::reverse(id_vector.begin(), id_vector.end() );
}
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id == phantom_node_pair.target_phantom.packed_geometry_id) && unpacked_path.empty();
int start_index = 0;
int end_index = phantom_node_pair.target_phantom.fwd_segment_position;
if (target_traversed_in_reverse)
{
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
}
if (is_local_path)
{
start_index = phantom_node_pair.source_phantom.fwd_segment_position;
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
if (target_traversed_in_reverse)
{
start_index = id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
}
}
BOOST_ASSERT(start_index >= 0);
for (int i = start_index; i != end_index; (start_index < end_index ? ++i :--i))
{
BOOST_ASSERT( i >= -1 );
unpacked_path.push_back(
PathData(
ed.id,
facade->GetNameIndexFromEdgeID(ed.id),
facade->GetTurnInstructionForEdgeID(ed.id),
ed.distance
id_vector[i],
phantom_node_pair.target_phantom.name_id,
TurnInstructionsClass::NoTurn,
0
)
);
}
}
// there is no equivalent to a node-based node in an edge-expanded graph.
// two equivalent routes may start (or end) at different node-based edges
// as they are added with the offset how much "distance" on the edge
// has already been traversed. Depending on offset one needs to remove
// the last node.
if (unpacked_path.size() > 1)
{
const unsigned last_index = unpacked_path.size()-1;
const unsigned second_to_last_index = last_index -1;
//looks like a trivially true check but tests for underflow
BOOST_ASSERT(last_index > second_to_last_index);
if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node)
{
unpacked_path.pop_back();
}
BOOST_ASSERT(!unpacked_path.empty());
}
}
inline void UnpackEdge(
const NodeID s,
const NodeID t,
std::vector<NodeID> & unpacked_path
) const {
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpacked_path) const
{
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
recursion_stack.push(std::make_pair(s,t));
std::pair<NodeID, NodeID> edge;
while(!recursion_stack.empty()) {
while (!recursion_stack.empty())
{
edge = recursion_stack.top();
recursion_stack.pop();
EdgeID smaller_edge_id = SPECIAL_EDGEID;
int edge_weight = INT_MAX;
for(
EdgeID edge_id = facade->BeginEdges(edge.first);
edge_id < facade->EndEdges(edge.first);
++edge_id
){
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
{
const int weight = facade->GetEdgeData(edge_id).distance;
if(
(facade->GetTarget(edge_id) == edge.second) &&
@ -241,18 +326,13 @@ public:
}
}
if( SPECIAL_EDGEID == smaller_edge_id ){
for(
EdgeID edge_id = facade->BeginEdges(edge.second);
edge_id < facade->EndEdges(edge.second);
++edge_id
){
if (SPECIAL_EDGEID == smaller_edge_id)
{
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
{
const int weight = facade->GetEdgeData(edge_id).distance;
if(
(facade->GetTarget(edge_id) == edge.first) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).backward
){
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
{
smaller_edge_id = edge_id;
edge_weight = weight;
}
@ -261,16 +341,15 @@ public:
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
if(ed.shortcut) {//unpack
if (ed.shortcut)
{//unpack
const NodeID middle_node_id = ed.id;
//again, we need to this in reversed order
recursion_stack.push(
std::make_pair(middle_node_id, edge.second)
);
recursion_stack.push(
std::make_pair(edge.first, middle_node_id)
);
} else {
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
}
else
{
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
unpacked_path.push_back(edge.first );
}
@ -279,43 +358,41 @@ public:
}
inline void RetrievePackedPathFromHeap(
SearchEngineData::QueryHeap & forward_heap,
SearchEngineData::QueryHeap & reverse_heap,
const SearchEngineData::QueryHeap & forward_heap,
const SearchEngineData::QueryHeap & reverse_heap,
const NodeID middle_node_id,
std::vector<NodeID> & packed_path
) const {
) const
{
NodeID current_node_id = middle_node_id;
while(current_node_id != forward_heap.GetData(current_node_id).parent) {
while(current_node_id != forward_heap.GetData(current_node_id).parent)
{
current_node_id = forward_heap.GetData(current_node_id).parent;
packed_path.push_back(current_node_id);
}
std::reverse(packed_path.begin(), packed_path.end());
packed_path.push_back(middle_node_id);
current_node_id = middle_node_id;
while (current_node_id != reverse_heap.GetData(current_node_id).parent){
while (current_node_id != reverse_heap.GetData(current_node_id).parent)
{
current_node_id = reverse_heap.GetData(current_node_id).parent;
packed_path.push_back(current_node_id);
}
}
//TODO: reorder parameters
inline void RetrievePackedPathFromSingleHeap(
SearchEngineData::QueryHeap & search_heap,
const SearchEngineData::QueryHeap & search_heap,
const NodeID middle_node_id,
std::vector<NodeID>& packed_path
) const {
) const
{
NodeID current_node_id = middle_node_id;
while(current_node_id != search_heap.GetData(current_node_id).parent) {
while(current_node_id != search_heap.GetData(current_node_id).parent)
{
current_node_id = search_heap.GetData(current_node_id).parent;
packed_path.push_back(current_node_id);
}
}
int ComputeEdgeOffset(const PhantomNode & phantom) const {
return phantom.weight1 + (phantom.isBidirected() ? phantom.weight2 : 0);
}
};
#endif /* BASICROUTINGINTERFACE_H_ */

View File

@ -48,21 +48,22 @@ public:
) :
super(facade),
engine_working_data(engine_working_data)
{}
{ }
~ShortestPathRouting() {}
~ShortestPathRouting() { }
void operator()(
const std::vector<PhantomNodes> & phantom_nodes_vector,
RawRouteData & raw_route_data
) const {
) const
{
BOOST_FOREACH(
const PhantomNodes & phantom_node_pair,
phantom_nodes_vector
){
if(!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) {
raw_route_data.lengthOfShortestPath = INT_MAX;
raw_route_data.lengthOfAlternativePath = INT_MAX;
if( phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ) {
// raw_route_data.lengthOfShortestPath = INT_MAX;
// raw_route_data.lengthOfAlternativePath = INT_MAX;
return;
}
}
@ -104,71 +105,84 @@ public:
middle2 = UINT_MAX;
//insert new starting nodes into forward heap, adjusted by previous distances.
if(search_from_1st_node) {
if(
search_from_1st_node &&
phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID
) {
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset();
forward_heap1.Insert(
phantom_node_pair.startPhantom.edgeBasedNode,
distance1-phantom_node_pair.startPhantom.weight1,
phantom_node_pair.startPhantom.edgeBasedNode
phantom_node_pair.source_phantom.forward_node_id,
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.source_phantom.forward_node_id
);
forward_heap2.Insert(
phantom_node_pair.startPhantom.edgeBasedNode,
distance1-phantom_node_pair.startPhantom.weight1,
phantom_node_pair.startPhantom.edgeBasedNode
phantom_node_pair.source_phantom.forward_node_id,
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.source_phantom.forward_node_id
);
}
if(phantom_node_pair.startPhantom.isBidirected() && search_from_2nd_node) {
if(
search_from_2nd_node &&
phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID
) {
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
forward_heap1.Insert(
phantom_node_pair.startPhantom.edgeBasedNode+1,
distance2-phantom_node_pair.startPhantom.weight2,
phantom_node_pair.startPhantom.edgeBasedNode+1
phantom_node_pair.source_phantom.reverse_node_id,
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.source_phantom.reverse_node_id
);
forward_heap2.Insert(
phantom_node_pair.startPhantom.edgeBasedNode+1,
distance2-phantom_node_pair.startPhantom.weight2,
phantom_node_pair.startPhantom.edgeBasedNode+1
phantom_node_pair.source_phantom.reverse_node_id,
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.source_phantom.reverse_node_id
);
}
//insert new backward nodes into backward heap, unadjusted.
reverse_heap1.Insert(
phantom_node_pair.targetPhantom.edgeBasedNode,
phantom_node_pair.targetPhantom.weight1,
phantom_node_pair.targetPhantom.edgeBasedNode
);
if(phantom_node_pair.targetPhantom.isBidirected() ) {
reverse_heap2.Insert(
phantom_node_pair.targetPhantom.edgeBasedNode+1,
phantom_node_pair.targetPhantom.weight2,
phantom_node_pair.targetPhantom.edgeBasedNode+1
if( phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID ) {
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset();
reverse_heap1.Insert(
phantom_node_pair.target_phantom.forward_node_id,
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.target_phantom.forward_node_id
);
}
const int forward_offset = super::ComputeEdgeOffset(
phantom_node_pair.startPhantom
);
const int reverse_offset = super::ComputeEdgeOffset(
phantom_node_pair.targetPhantom
);
if( phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID ) {
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset();
reverse_heap2.Insert(
phantom_node_pair.target_phantom.reverse_node_id,
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.target_phantom.reverse_node_id
);
}
// const int forward_offset = phantom_node_pair.ComputeForwardQueueOffset();
// const int forward_offset = super::ComputeForwardOffset(
// phantom_node_pair.source_phantom
// );
// const int reverse_offset = -phantom_node_pair.ComputeReverseQueueOffset();
// const int reverse_offset = super::ComputeReverseOffset(
// phantom_node_pair.target_phantom
// );
//run two-Target Dijkstra routing step.
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
if( !forward_heap1.Empty()){
if( 0 < forward_heap1.Size() ){
super::RoutingStep(
forward_heap1,
reverse_heap1,
&middle1,
&local_upper_bound1,
forward_offset,
true
);
}
if( !reverse_heap1.Empty() ){
if( 0 < reverse_heap1.Size() ){
super::RoutingStep(
reverse_heap1,
forward_heap1,
&middle1,
&local_upper_bound1,
reverse_offset,
false
);
}
@ -176,23 +190,21 @@ public:
if( !reverse_heap2.Empty() ) {
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
if( !forward_heap2.Empty() ){
if( 0 < forward_heap2.Size() ){
super::RoutingStep(
forward_heap2,
reverse_heap2,
&middle2,
&local_upper_bound2,
forward_offset,
true
);
}
if( !reverse_heap2.Empty() ){
if( 0 < reverse_heap2.Size() ){
super::RoutingStep(
reverse_heap2,
forward_heap2,
&middle2,
&local_upper_bound2,
reverse_offset,
false
);
}
@ -201,17 +213,17 @@ public:
//No path found for both target nodes?
if(
(INT_MAX == local_upper_bound1) &&
(INT_MAX == local_upper_bound2)
(INVALID_EDGE_WEIGHT == local_upper_bound1) &&
(INVALID_EDGE_WEIGHT == local_upper_bound2)
) {
raw_route_data.lengthOfShortestPath = INT_MAX;
raw_route_data.lengthOfAlternativePath = INT_MAX;
raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT;
raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT;
return;
}
if(UINT_MAX == middle1) {
if( SPECIAL_NODEID == middle1 ) {
search_from_1st_node = false;
}
if(UINT_MAX == middle2) {
if( SPECIAL_NODEID == middle2 ) {
search_from_2nd_node = false;
}
@ -228,7 +240,7 @@ public:
BOOST_ASSERT( (unsigned)current_leg < packed_legs1.size() );
BOOST_ASSERT( (unsigned)current_leg < packed_legs2.size() );
if(INT_MAX != local_upper_bound1) {
if( INVALID_EDGE_WEIGHT != local_upper_bound1 ) {
super::RetrievePackedPathFromHeap(
forward_heap1,
reverse_heap1,
@ -237,7 +249,7 @@ public:
);
}
if(INT_MAX != local_upper_bound2) {
if( INVALID_EDGE_WEIGHT != local_upper_bound2 ) {
super::RetrievePackedPathFromHeap(
forward_heap2,
reverse_heap2,
@ -264,8 +276,6 @@ public:
local_upper_bound2 = local_upper_bound1;
}
// SimpleLogger().Write() << "fetched packed paths";
BOOST_ASSERT_MSG(
!temporary_packed_leg1.empty() ||
!temporary_packed_leg2.empty(),
@ -335,11 +345,11 @@ public:
if(
(packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
phantom_node_pair.targetPhantom.isBidirected()
phantom_node_pair.target_phantom.isBidirected()
) {
const NodeID last_node_id = packed_legs2[current_leg].back();
search_from_1st_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode+1);
search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode);
search_from_1st_node &= !(last_node_id == phantom_node_pair.target_phantom.reverse_node_id);
search_from_2nd_node &= !(last_node_id == phantom_node_pair.target_phantom.forward_node_id);
BOOST_ASSERT( search_from_1st_node != search_from_2nd_node );
}
@ -348,14 +358,42 @@ public:
++current_leg;
}
if( distance1 > distance2 ) {
if (distance1 > distance2)
{
std::swap( packed_legs1, packed_legs2 );
}
raw_route_data.unpacked_path_segments.resize( packed_legs1.size() );
for(unsigned i = 0; i < packed_legs1.size(); ++i){
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size() );
// const int start_offset = ( packed_legs1[0].front() == phantom_nodes_vector.front().source_phantom.forward_node_id ? 1 : -1 )*phantom_nodes_vector.front().source_phantom.fwd_segment_position;
raw_route_data.source_traversed_in_reverse = (packed_legs1.front().front() != phantom_nodes_vector.front().source_phantom.forward_node_id);
raw_route_data.target_traversed_in_reverse = (packed_legs1.back().back() != phantom_nodes_vector.back().target_phantom.forward_node_id);
for (unsigned i = 0; i < packed_legs1.size(); ++i)
{
BOOST_ASSERT(!phantom_nodes_vector.empty());
// const bool at_beginning = (packed_legs1[i] == packed_legs1.front());
// const bool at_end = (packed_legs1[i] == packed_legs1.back());
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size());
PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i];
// if (!at_beginning)
// {
// unpack_phantom_node_pair.source_phantom.packed_geometry_id = SPECIAL_EDGEID;
// unpack_phantom_node_pair.source_phantom.fwd_segment_position = 0;
// }
// if (!at_end)
// {
// unpack_phantom_node_pair.target_phantom.packed_geometry_id = SPECIAL_EDGEID;
// unpack_phantom_node_pair.target_phantom.fwd_segment_position = 0;
// }
super::UnpackPath(
// -- packed input
packed_legs1[i],
// -- start and end of (sub-)route
unpack_phantom_node_pair,
// -- unpacked output
raw_route_data.unpacked_path_segments[i]
);
}

View File

@ -86,6 +86,15 @@ public:
const unsigned id
) const = 0;
virtual bool EdgeIsCompressed( const unsigned id ) const = 0;
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0;
virtual void GetUncompressedGeometry(
const unsigned id,
std::vector<unsigned> & result_nodes
) const = 0;
virtual TurnInstruction GetTurnInstructionForEdgeID(
const unsigned id
) const = 0;

View File

@ -45,6 +45,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/Coordinate.h>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
template<class EdgeDataT>
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
@ -61,14 +64,23 @@ private:
QueryGraph * m_query_graph;
std::string m_timestamp;
ShM<FixedPointCoordinate, false>::vector m_coordinate_list;
boost::shared_ptr<ShM<FixedPointCoordinate, false>::vector> m_coordinate_list;
ShM<NodeID, false>::vector m_via_node_list;
ShM<unsigned, false>::vector m_name_ID_list;
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
ShM<char, false>::vector m_names_char_list;
ShM<unsigned, false>::vector m_name_begin_indices;
ShM<bool, false>::vector m_egde_is_compressed;
ShM<unsigned, false>::vector m_geometry_indices;
ShM<unsigned, false>::vector m_geometry_list;
StaticRTree<RTreeLeaf, false> * m_static_rtree;
boost::shared_ptr<
StaticRTree<
RTreeLeaf,
ShM<FixedPointCoordinate, false>::vector,
false
>
> m_static_rtree;
void LoadTimestamp(const boost::filesystem::path & timestamp_path) {
@ -103,7 +115,7 @@ private:
);
BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty");
BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
// BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() << " edges";
m_query_graph = new QueryGraph(node_list, edge_list);
@ -113,42 +125,44 @@ private:
}
void LoadNodeAndEdgeInformation(
const boost::filesystem::path nodes_file,
const boost::filesystem::path edges_file
const boost::filesystem::path & nodes_file,
const boost::filesystem::path & edges_file
) {
boost::filesystem::ifstream nodes_input_stream(
nodes_file,
std::ios::binary
);
SimpleLogger().Write(logDEBUG) << "Loading node data";
NodeInfo current_node;
unsigned number_of_coordinates = 0;
nodes_input_stream.read(
(char *)&number_of_coordinates,
sizeof(unsigned)
);
m_coordinate_list.resize(number_of_coordinates);
m_coordinate_list = boost::make_shared<std::vector<FixedPointCoordinate> >(number_of_coordinates);
for(unsigned i = 0; i < number_of_coordinates; ++i) {
nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
m_coordinate_list[i] = FixedPointCoordinate(
m_coordinate_list->at(i) = FixedPointCoordinate(
current_node.lat,
current_node.lon
);
BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lat) >> 30) == 0 );
BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lon) >> 30) == 0 );
}
std::vector<FixedPointCoordinate>(m_coordinate_list).swap(m_coordinate_list);
nodes_input_stream.close();
SimpleLogger().Write(logDEBUG) << "Loading edge data";
boost::filesystem::ifstream edges_input_stream(
edges_file,
std::ios::binary
);
unsigned number_of_edges = 0;
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
m_via_node_list.resize(number_of_edges);
m_name_ID_list.resize(number_of_edges);
m_via_node_list.resize (number_of_edges);
m_name_ID_list.resize (number_of_edges);
m_turn_instruction_list.resize(number_of_edges);
m_egde_is_compressed.resize (number_of_edges);
unsigned compressed = 0;
OriginalEdgeData current_edge_data;
for(unsigned i = 0; i < number_of_edges; ++i) {
@ -159,17 +173,63 @@ private:
m_via_node_list[i] = current_edge_data.via_node;
m_name_ID_list[i] = current_edge_data.name_id;
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
m_egde_is_compressed[i] = current_edge_data.compressed_geometry;
if(m_egde_is_compressed[i]) {
++compressed;
}
}
edges_input_stream.close();
}
void LoadGeometries(const boost::filesystem::path & geometry_file)
{
std::ifstream geometry_stream(
geometry_file.c_str(),
std::ios::binary
);
unsigned number_of_indices = 0;
unsigned number_of_compressed_geometries = 0;
geometry_stream.read(
(char *)&number_of_indices,
sizeof(unsigned)
);
m_geometry_indices.resize(number_of_indices);
geometry_stream.read(
(char *)&(m_geometry_indices[0]),
number_of_indices*sizeof(unsigned)
);
geometry_stream.read(
(char *)&number_of_compressed_geometries,
sizeof(unsigned)
);
BOOST_ASSERT( m_geometry_indices.back() == number_of_compressed_geometries );
m_geometry_list.resize( number_of_compressed_geometries );
geometry_stream.read(
(char *)&(m_geometry_list[0]),
number_of_compressed_geometries*sizeof(unsigned)
);
geometry_stream.close();
}
void LoadRTree(
const boost::filesystem::path & ram_index_path,
const boost::filesystem::path & file_index_path
) {
m_static_rtree = new StaticRTree<RTreeLeaf>(
BOOST_ASSERT_MSG(
!m_coordinate_list->empty(),
"coordinates must be loaded before r-tree"
);
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf> >(
ram_index_path,
file_index_path
file_index_path,
m_coordinate_list
);
}
@ -204,7 +264,7 @@ private:
public:
~InternalDataFacade() {
delete m_query_graph;
delete m_static_rtree;
m_static_rtree.reset();
}
explicit InternalDataFacade( const ServerPaths & server_paths ) {
@ -218,6 +278,9 @@ public:
if( server_paths.find("fileindex") == server_paths.end() ) {
throw OSRMException("no leaf index file given in ini file");
}
if( server_paths.find("geometries") == server_paths.end() ) {
throw OSRMException("no geometries file given in ini file");
}
if( server_paths.find("nodesdata") == server_paths.end() ) {
throw OSRMException("no nodes file given in ini file");
}
@ -249,12 +312,17 @@ public:
paths_iterator = server_paths.find("namesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & names_data_path = paths_iterator->second;
paths_iterator = server_paths.find("geometries");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & geometries_path = paths_iterator->second;
//load data
SimpleLogger().Write() << "loading graph data";
LoadGraph(hsgr_path);
SimpleLogger().Write() << "loading egde information";
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
SimpleLogger().Write() << "loading geometries";
LoadGeometries( geometries_path );
SimpleLogger().Write() << "loading r-tree";
LoadRTree(ram_index_path, file_index_path);
SimpleLogger().Write() << "loading timestamp";
@ -319,10 +387,13 @@ public:
FixedPointCoordinate GetCoordinateOfNode(
const unsigned id
) const {
const NodeID node = m_via_node_list.at(id);
return m_coordinate_list.at(node);
return m_coordinate_list->at(id);
};
bool EdgeIsCompressed( const unsigned id ) const {
return m_egde_is_compressed.at(id);
}
TurnInstruction GetTurnInstructionForEdgeID(
const unsigned id
) const {
@ -346,11 +417,12 @@ public:
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const {
return m_static_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
return found;
}
unsigned GetCheckSum() const { return m_check_sum; }
@ -368,8 +440,8 @@ public:
name_id < m_name_begin_indices.size(),
"name id too high"
);
unsigned begin_index = m_name_begin_indices[name_id];
unsigned end_index = m_name_begin_indices[name_id+1];
const unsigned begin_index = m_name_begin_indices[name_id];
const unsigned end_index = m_name_begin_indices[name_id+1];
BOOST_ASSERT_MSG(
begin_index < m_names_char_list.size(),
"begin index of name too high"
@ -389,6 +461,22 @@ public:
);
}
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const {
return m_via_node_list.at(id);
}
virtual void GetUncompressedGeometry(
const unsigned id, std::vector<unsigned> & result_nodes
) const {
const unsigned begin = m_geometry_indices.at(id);
const unsigned end = m_geometry_indices.at(id+1);
result_nodes.clear();
result_nodes.insert(result_nodes.begin(),
m_geometry_list.begin() + begin,
m_geometry_list.begin() + end);
}
std::string GetTimestamp() const {
return m_timestamp;
}

View File

@ -30,9 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//implements all data storage when shared memory _IS_ used
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include "BaseDataFacade.h"
#include "SharedDataType.h"
@ -42,6 +39,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../../Util/ProgramOptions.h"
#include "../../Util/SimpleLogger.h"
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <algorithm>
template<class EdgeDataT>
@ -55,7 +55,7 @@ private:
typedef typename StaticGraph<EdgeData, true>::_StrEdge GraphEdge;
typedef typename QueryGraph::InputEdge InputEdge;
typedef typename super::RTreeLeaf RTreeLeaf;
typedef typename StaticRTree<RTreeLeaf, true>::TreeNode RTreeNode;
typedef typename StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode RTreeNode;
SharedDataLayout * data_layout;
char * shared_memory;
@ -72,15 +72,25 @@ private:
boost::shared_ptr<SharedMemory> m_large_memory;
std::string m_timestamp;
ShM<FixedPointCoordinate, true>::vector m_coordinate_list;
boost::shared_ptr<
ShM<FixedPointCoordinate, true>::vector
> m_coordinate_list;
ShM<NodeID, true>::vector m_via_node_list;
ShM<unsigned, true>::vector m_name_ID_list;
ShM<TurnInstruction, true>::vector m_turn_instruction_list;
ShM<char, true>::vector m_names_char_list;
ShM<unsigned, true>::vector m_name_begin_indices;
boost::shared_ptr<StaticRTree<RTreeLeaf, true> > m_static_rtree;
ShM<bool, true>::vector m_egde_is_compressed;
ShM<unsigned, true>::vector m_geometry_indices;
ShM<unsigned, true>::vector m_geometry_list;
// SharedDataFacade() { }
boost::shared_ptr<
StaticRTree<
RTreeLeaf,
ShM<FixedPointCoordinate, true>::vector,
true
>
> m_static_rtree;
void LoadTimestamp() {
char * timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset();
@ -95,13 +105,19 @@ private:
void LoadRTree(
const boost::filesystem::path & file_index_path
) {
BOOST_ASSERT_MSG(
!m_coordinate_list->empty(),
"coordinates must be loaded before r-tree"
);
RTreeNode * tree_ptr = (RTreeNode *)(
shared_memory + data_layout->GetRSearchTreeOffset()
);
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf, true> >(
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true> >(
tree_ptr,
data_layout->r_search_tree_size,
file_index_path
file_index_path,
m_coordinate_list
);
}
@ -112,7 +128,7 @@ private:
);
GraphEdge * graph_edges_ptr = (GraphEdge *)(
shared_memory + data_layout->GetGraphEdgeListOffsett()
shared_memory + data_layout->GetGraphEdgeListOffset()
);
typename ShM<GraphNode, true>::vector node_list(
@ -126,7 +142,6 @@ private:
m_query_graph.reset(
new QueryGraph(node_list, edge_list)
);
}
void LoadNodeAndEdgeInformation() {
@ -134,11 +149,10 @@ private:
FixedPointCoordinate * coordinate_list_ptr = (FixedPointCoordinate *)(
shared_memory + data_layout->GetCoordinateListOffset()
);
typename ShM<FixedPointCoordinate, true>::vector coordinate_list(
m_coordinate_list = boost::make_shared<ShM<FixedPointCoordinate, true>::vector> (
coordinate_list_ptr,
data_layout->coordinate_list_size
);
m_coordinate_list.swap( coordinate_list );
TurnInstruction * turn_instruction_list_ptr = (TurnInstruction *)(
shared_memory + data_layout->GetTurnInstructionListOffset()
@ -190,6 +204,36 @@ private:
m_names_char_list.swap(names_char_list);
}
void LoadGeometries()
{
unsigned * geometries_compressed_ptr = (unsigned *)(
shared_memory + data_layout->GetGeometriesIndicatorOffset()
);
typename ShM<bool, true>::vector egde_is_compressed(
geometries_compressed_ptr,
data_layout->geometries_indicators
);
m_egde_is_compressed.swap(egde_is_compressed);
unsigned * geometries_index_ptr = (unsigned *)(
shared_memory + data_layout->GetGeometriesIndexListOffset()
);
typename ShM<unsigned, true>::vector geometry_begin_indices(
geometries_index_ptr,
data_layout->geometries_index_list_size
);
m_geometry_indices.swap(geometry_begin_indices);
unsigned * geometries_list_ptr = (unsigned *)(
shared_memory + data_layout->GetGeometryListOffset()
);
typename ShM<unsigned, true>::vector geometry_list(
geometries_list_ptr,
data_layout->geometries_list_size
);
m_geometry_list.swap(geometry_list);
}
public:
SharedDataFacade( ) {
data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
@ -241,6 +285,7 @@ public:
LoadGraph();
LoadNodeAndEdgeInformation();
LoadGeometries();
LoadRTree(ram_index_path);
LoadTimestamp();
LoadViaNodeList();
@ -250,7 +295,6 @@ public:
}
}
//search graph access
unsigned GetNumberOfNodes() const {
return m_query_graph->GetNumberOfNodes();
@ -307,10 +351,29 @@ public:
FixedPointCoordinate GetCoordinateOfNode(
const unsigned id
) const {
const NodeID node = m_via_node_list.at(id);
return m_coordinate_list.at(node);
return m_coordinate_list->at(id);
};
virtual bool EdgeIsCompressed( const unsigned id ) const {
return m_egde_is_compressed.at(id);
}
virtual void GetUncompressedGeometry(
const unsigned id, std::vector<unsigned> & result_nodes
) const {
const unsigned begin = m_geometry_indices.at(id);
const unsigned end = m_geometry_indices.at(id+1);
result_nodes.clear();
result_nodes.insert(result_nodes.begin(),
m_geometry_list.begin() + begin,
m_geometry_list.begin() + end);
}
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const {
return m_via_node_list.at(id);
}
TurnInstruction GetTurnInstructionForEdgeID(
const unsigned id
) const {
@ -334,11 +397,12 @@ public:
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const {
return m_static_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
return found;
}
unsigned GetCheckSum() const { return m_check_sum; }

View File

@ -43,7 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/integer.hpp>
typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf;
typedef StaticRTree<RTreeLeaf, true>::TreeNode RTreeNode;
typedef StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode RTreeNode;
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
struct SharedDataLayout {
@ -56,6 +56,9 @@ struct SharedDataLayout {
uint64_t coordinate_list_size;
uint64_t turn_instruction_list_size;
uint64_t r_search_tree_size;
uint64_t geometries_index_list_size;
uint64_t geometries_list_size;
uint64_t geometries_indicators;
unsigned checksum;
unsigned timestamp_length;
@ -72,8 +75,12 @@ struct SharedDataLayout {
coordinate_list_size(0),
turn_instruction_list_size(0),
r_search_tree_size(0),
geometries_index_list_size(0),
geometries_list_size(0),
geometries_indicators(0),
checksum(0),
timestamp_length(0)
{
ram_index_file_name[0] = '\0';
}
@ -90,23 +97,29 @@ struct SharedDataLayout {
SimpleLogger().Write(logDEBUG) << "coordinate_list_size: " << coordinate_list_size;
SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << turn_instruction_list_size;
SimpleLogger().Write(logDEBUG) << "r_search_tree_size: " << r_search_tree_size;
SimpleLogger().Write(logDEBUG) << "geometries_indicators: " << geometries_indicators << "/" << ((geometries_indicators/8) + 1);
SimpleLogger().Write(logDEBUG) << "geometries_index_list_size: " << geometries_index_list_size;
SimpleLogger().Write(logDEBUG) << "geometries_list_size: " << geometries_list_size;
SimpleLogger().Write(logDEBUG) << "sizeof(checksum): " << sizeof(checksum);
SimpleLogger().Write(logDEBUG) << "ram index file name: " << ram_index_file_name;
}
uint64_t GetSizeOfLayout() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
(r_search_tree_size * sizeof(RTreeNode) ) +
sizeof(checksum) +
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) ) +
(geometries_indicators/32 + 1) * sizeof(unsigned) +
(geometries_index_list_size * sizeof(unsigned) ) +
(geometries_list_size * sizeof(unsigned) ) +
sizeof(checksum) +
1024*sizeof(char);
return result;
}
@ -140,10 +153,10 @@ struct SharedDataLayout {
(via_node_list_size * sizeof(NodeID) );
return result;
}
uint64_t GetGraphEdgeListOffsett() const {
uint64_t GetGraphEdgeListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) ;
@ -184,29 +197,79 @@ struct SharedDataLayout {
}
uint64_t GetRSearchTreeOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
(turn_instruction_list_size * sizeof(TurnInstructions) );
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass));
return result;
}
uint64_t GetGeometriesIndicatorOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) );
return result;
}
uint64_t GetGeometriesIndexListOffset() const
{ uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) ) +
(geometries_indicators/32 + 1) * sizeof(unsigned);
return result;
}
uint64_t GetGeometryListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) ) +
(geometries_indicators/32 + 1) * sizeof(unsigned) +
(geometries_index_list_size * sizeof(unsigned) );
return result;
}
uint64_t GetChecksumOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
(r_search_tree_size * sizeof(RTreeNode) );
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) ) +
(geometries_indicators/32 + 1) * sizeof(unsigned) +
(geometries_index_list_size * sizeof(unsigned) ) +
(geometries_list_size * sizeof(unsigned) );
return result;
}
};

View File

@ -25,14 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "RequestHandler.h"
#include "APIGrammar.h"
#include "RequestHandler.h"
#include "Http/Request.h"
#include "../Library/OSRM.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>
#include <boost/foreach.hpp>

View File

@ -28,10 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H
#include "Http/Request.h"
#include <osrm/Reply.h>
#include <boost/noncopyable.hpp>
#include <string>
@ -41,6 +37,11 @@ struct APIGrammar;
struct RouteParameters;
class OSRM;
namespace http {
class Reply;
struct Request;
}
class RequestHandler : private boost::noncopyable {
public:

View File

@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/unordered_map.hpp>
@ -135,7 +136,7 @@ NodeID readBinaryOSRMGraphFromStream(
short type;
NodeID nameID;
int length;
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow;
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, is_split;
for (EdgeID i=0; i<m; ++i) {
input_stream.read((char*)&source, sizeof(unsigned));
@ -149,6 +150,7 @@ NodeID readBinaryOSRMGraphFromStream(
input_stream.read((char*)&ignoreInGrid, sizeof(bool));
input_stream.read((char*)&isAccessRestricted, sizeof(bool));
input_stream.read((char*)&isContraFlow, sizeof(bool));
input_stream.read((char*)&is_split, sizeof(bool));
BOOST_ASSERT_MSG(length > 0, "loaded null length edge" );
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
@ -189,7 +191,7 @@ NodeID readBinaryOSRMGraphFromStream(
std::swap(forward, backward);
}
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow );
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, is_split );
edge_list.push_back(inputEdge);
}
std::sort(edge_list.begin(), edge_list.end());
@ -444,7 +446,10 @@ unsigned readHSGRFromStream(
hsgr_input_stream.read( (char*) &number_of_nodes, sizeof(unsigned) );
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
hsgr_input_stream.read( (char*) &number_of_edges, sizeof(unsigned) );
BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes << ", number_of_edges: " << number_of_edges;
// BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
node_list.resize(number_of_nodes + 1);
hsgr_input_stream.read(
(char*) &(node_list[0]),
@ -457,6 +462,7 @@ unsigned readHSGRFromStream(
number_of_edges*sizeof(EdgeT)
);
hsgr_input_stream.close();
return number_of_nodes;
}

View File

@ -110,6 +110,10 @@ inline unsigned GenerateServerProgramOptions(
"edgesdata",
boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
".edges file")
(
"geometry",
boost::program_options::value<boost::filesystem::path>(&paths["geometries"]),
".geometry file")
(
"ramindex",
boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
@ -252,6 +256,17 @@ inline unsigned GenerateServerProgramOptions(
}
path_iterator = paths.find("geometries");
if(
path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second)
) {
path_iterator->second = base_string + ".geometry";
} else {
throw OSRMException(base_string + ".geometry not found");
}
path_iterator = paths.find("ramindex");
if(
path_iterator != paths.end() &&

View File

@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/noncopyable.hpp>
#include <boost/thread/mutex.hpp>
#include <cstdio>
#include <ostream>
#include <iostream>
@ -70,16 +72,20 @@ private:
bool m_is_mute;
};
class SimpleLogger {
class SimpleLogger
{
public:
SimpleLogger() : level(logINFO) { }
std::ostringstream& Write(LogLevel l = logINFO) {
try {
std::ostringstream& Write(LogLevel l = logINFO)
{
try
{
boost::mutex::scoped_lock lock(logger_mutex);
level = l;
os << "[";
switch(level) {
switch(level)
{
case logINFO:
os << "info";
break;
@ -96,22 +102,26 @@ public:
break;
}
os << "] ";
} catch (...) { }
}
catch (...) { }
return os;
}
virtual ~SimpleLogger() {
if(!LogPolicy::GetInstance().IsMute()) {
switch(level) {
if(!LogPolicy::GetInstance().IsMute())
{
const bool is_terminal = isatty(fileno(stdout));
switch(level)
{
case logINFO:
std::cout << os.str() << std::endl;
std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
break;
case logWARNING:
std::cerr << RED << os.str() << COL_RESET << std::endl;
std::cerr << (is_terminal ? RED : "") << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
break;
case logDEBUG:
#ifndef NDEBUG
std::cout << YELLOW << os.str() << COL_RESET << std::endl;
std::cout << (is_terminal ? YELLOW : "") << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
#endif
break;
default:

View File

@ -44,9 +44,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sys/mman.h>
#endif
#include <boost/integer.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/integer.hpp>
#include <boost/iostreams/seek.hpp>
#include <fstream>
#include <string>
#include <vector>
@ -137,6 +139,10 @@ int main( const int argc, const char * argv[] ) {
BOOST_ASSERT(!paths_iterator->second.empty());
const boost::filesystem::path & names_data_path = paths_iterator->second;
paths_iterator = server_paths.find("geometries");
BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty());
const boost::filesystem::path & geometries_data_path = paths_iterator->second;
// get the shared memory segment to use
bool use_first_segment = SharedMemory::RegionExists( LAYOUT_2 );
@ -163,7 +169,6 @@ int main( const int argc, const char * argv[] ) {
shared_layout_ptr->ram_index_file_name[end_of_string_index] = '\0';
// collect number of elements to store in shared memory object
SimpleLogger().Write(logDEBUG) << "Collecting files sizes";
SimpleLogger().Write() << "load names from: " << names_data_path;
// number of entries in name index
boost::filesystem::ifstream name_stream(
@ -192,6 +197,7 @@ int main( const int argc, const char * argv[] ) {
shared_layout_ptr->via_node_list_size = number_of_original_edges;
shared_layout_ptr->name_id_list_size = number_of_original_edges;
shared_layout_ptr->turn_instruction_list_size = number_of_original_edges;
shared_layout_ptr->geometries_indicators = number_of_original_edges;
boost::filesystem::ifstream hsgr_input_stream(
hsgr_path,
@ -276,8 +282,21 @@ int main( const int argc, const char * argv[] ) {
shared_layout_ptr->coordinate_list_size = coordinate_list_size;
// allocate shared memory block
// load geometries sizes
std::ifstream geometry_input_stream(
geometries_data_path.c_str(),
std::ios::binary
);
unsigned number_of_geometries_indices = 0;
unsigned number_of_compressed_geometries = 0;
geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned));
shared_layout_ptr->geometries_index_list_size = number_of_geometries_indices;
boost::iostreams::seek(geometry_input_stream, number_of_geometries_indices*sizeof(unsigned), BOOST_IOS::cur);
geometry_input_stream.read( (char *)&number_of_compressed_geometries, sizeof(unsigned));
shared_layout_ptr->geometries_list_size = number_of_compressed_geometries;
// allocate shared memory block
SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout() << " bytes";
SharedMemory * shared_memory = SharedMemoryFactory::Get(
DATA,
@ -287,11 +306,9 @@ int main( const int argc, const char * argv[] ) {
// read actual data into shared memory object //
// Loading street names
// SimpleLogger().Write() << "Loading names index and chars from: " << names_data_path.string();
unsigned * name_index_ptr = (unsigned*)(
shared_memory_ptr + shared_layout_ptr->GetNameIndexOffset()
);
// SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_index_list_size*sizeof(unsigned);
name_stream.read(
(char*)name_index_ptr,
@ -318,9 +335,12 @@ int main( const int argc, const char * argv[] ) {
shared_memory_ptr + shared_layout_ptr->GetTurnInstructionListOffset()
);
unsigned * geometries_indicator_ptr = (unsigned *)(
shared_memory_ptr + shared_layout_ptr->GetGeometriesIndicatorOffset()
);
OriginalEdgeData current_edge_data;
for(unsigned i = 0; i < number_of_original_edges; ++i) {
// SimpleLogger().Write() << i << "/" << number_of_edges;
edges_input_stream.read(
(char*)&(current_edge_data),
sizeof(OriginalEdgeData)
@ -328,9 +348,43 @@ int main( const int argc, const char * argv[] ) {
via_node_ptr[i] = current_edge_data.via_node;
name_id_ptr[i] = current_edge_data.name_id;
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
const unsigned bucket = i / 32;
const unsigned offset = i % 32;
unsigned value = ((0 == offset) ? 0 : geometries_indicator_ptr[bucket]);
if (current_edge_data.compressed_geometry)
{
geometries_indicator_ptr[bucket] = (value | (1 << offset));
}
}
edges_input_stream.close();
// load compressed geometry
unsigned temporary_value;
unsigned * geometries_index_ptr = (unsigned *)(
shared_memory_ptr + shared_layout_ptr->GetGeometriesIndexListOffset()
);
geometry_input_stream.seekg(0, geometry_input_stream.beg);
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
BOOST_ASSERT(temporary_value == shared_layout_ptr->geometries_index_list_size);
geometry_input_stream.read(
(char *)geometries_index_ptr,
shared_layout_ptr->geometries_index_list_size*sizeof(unsigned)
);
unsigned * geometries_list_ptr = (unsigned *)(
shared_memory_ptr + shared_layout_ptr->GetGeometryListOffset()
);
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
BOOST_ASSERT(temporary_value == shared_layout_ptr->geometries_list_size);
geometry_input_stream.read(
(char *)geometries_list_ptr,
shared_layout_ptr->geometries_list_size*sizeof(unsigned)
);
// Loading list of coordinates
FixedPointCoordinate * coordinates_ptr = (FixedPointCoordinate *)(
shared_memory_ptr + shared_layout_ptr->GetCoordinateListOffset()
@ -372,7 +426,7 @@ int main( const int argc, const char * argv[] ) {
// load the edges of the search graph
QueryGraph::_StrEdge * graph_edge_list_ptr = (QueryGraph::_StrEdge *)(
shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffsett()
shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffset()
);
hsgr_input_stream.read(
(char*) graph_edge_list_ptr,
@ -423,6 +477,8 @@ int main( const int argc, const char * argv[] ) {
}
}
SimpleLogger().Write() << "all data loaded";
shared_layout_ptr->PrintInformation();
} catch(const std::exception & e) {
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
}

View File

@ -43,6 +43,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdlib>
#include <boost/unordered_map.hpp>
#include <iostream>
#include <fstream>
#include <string>
@ -180,7 +182,7 @@ int main (int argc, char *argv[]) {
}
}
StringMap stringMap;
boost::unordered_map<std::string, NodeID> stringMap;
ExtractionContainers externalMemory;
stringMap[""] = 0;

View File

@ -16,9 +16,9 @@ When a max speed is set, osrm will use 2/3 of that as the actual speed.
| bc | trunk | 60 |
When I route I should get
| from | to | route | speed |
| a | b | ab | 85 km/h |
| b | c | bc | 40 km/h |
| from | to | route | speed |
| a | b | ab | 85 km/h |
| b | c | bc | 40 km/h +- 1 |
Scenario: Car - Do not ignore maxspeed when higher than way speed
Given the node map
@ -30,22 +30,22 @@ When a max speed is set, osrm will use 2/3 of that as the actual speed.
| bc | residential | 90 |
When I route I should get
| from | to | route | speed |
| a | b | ab | 25 km/h |
| b | c | bc | 60 km/h |
| from | to | route | speed |
| a | b | ab | 25 km/h |
| b | c | bc | 60 km/h +- 1 |
Scenario: Car - Forward/backward maxspeed
Given a grid size of 100 meters
Then routability should be
| highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw |
| primary | | | | 65 km/h | 65 km/h |
| primary | 60 | | | 40 km/h | 40 km/h |
| primary | | 60 | | 40 km/h | 65 km/h |
| primary | | | 60 | 65 km/h | 40 km/h |
| primary | 15 | 60 | | 40 km/h | 10 km/h |
| primary | 15 | | 60 | 10 km/h | 40 km/h |
| primary | 15 | 30 | 60 | 20 km/h | 40 km/h |
| highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw |
| primary | | | | 65 km/h | 65 km/h |
| primary | 60 | | | 40 km/h | 40 km/h |
| primary | | 60 | | 40 km/h | 65 km/h |
| primary | | | 60 | 65 km/h | 40 km/h |
| primary | 15 | 60 | | 40 km/h | 10 km/h +- 1 |
| primary | 15 | | 60 | 10 km/h +- 1| 40 km/h |
| primary | 15 | 30 | 60 | 20 km/h | 40 km/h |
Scenario: Car - Maxspeed should not allow routing on unroutable ways
Then routability should be
@ -62,4 +62,4 @@ When a max speed is set, osrm will use 2/3 of that as the actual speed.
| runway | | | | | | |
| runway | | | 100 | | | |
| runway | | | | 100 | | |
| runway | | | | | 100 | |
| runway | | | | | 100 | |

View File

@ -1,24 +1,24 @@
@routing @car @speed
@routing @car @speed
Feature: Car - speeds
Background:
Given the profile "car"
And a grid size of 1000 meters
Scenario: Car - speed of various way types
Then routability should be
| highway | oneway | bothw |
| motorway | no | 90 km/h |
| motorway_link | no | 75 km/h |
| trunk | no | 85 km/h |
| trunk_link | no | 70 km/h |
| primary | no | 65 km/h |
| primary_link | no | 60 km/h |
| secondary | no | 55 km/h |
| secondary_link | no | 50 km/h |
| tertiary | no | 40 km/h |
| tertiary_link | no | 30 km/h |
| unclassified | no | 25 km/h |
| residential | no | 25 km/h |
| living_street | no | 10 km/h |
| service | no | 15 km/h |
| highway | oneway | bothw |
| motorway | no | 90 km/h |
| motorway_link | no | 75 km/h |
| trunk | no | 85 km/h +- 1 |
| trunk_link | no | 70 km/h +- 1 |
| primary | no | 65 km/h +- 1 |
| primary_link | no | 60 km/h |
| secondary | no | 55 km/h +- 1 |
| secondary_link | no | 50 km/h |
| tertiary | no | 40 km/h |
| tertiary_link | no | 30 km/h |
| unclassified | no | 25 km/h |
| residential | no | 25 km/h |
| living_street | no | 10 km/h |
| service | no | 15 km/h |

View File

@ -25,7 +25,7 @@ Feature: osrm-routed command line options: help
And stdout should contain "--port"
And stdout should contain "--threads"
And stdout should contain "--sharedmemory"
And stdout should contain 21 lines
And stdout should contain 22 lines
And it should exit with code 0
Scenario: osrm-routed - Help, short
@ -49,7 +49,7 @@ Feature: osrm-routed command line options: help
And stdout should contain "--port"
And stdout should contain "--threads"
And stdout should contain "--sharedmemory"
And stdout should contain 21 lines
And stdout should contain 22 lines
And it should exit with code 0
Scenario: osrm-routed - Help, long
@ -73,5 +73,5 @@ Feature: osrm-routed command line options: help
And stdout should contain "--port"
And stdout should contain "--threads"
And stdout should contain "--sharedmemory"
And stdout should contain 21 lines
And it should exit with code 0
And stdout should contain 22 lines
And it should exit with code 0

View File

@ -11,7 +11,7 @@ def test_routability_row i
r[:status] = route_status r[:response]
if r[:status].empty? == false
r[:route] = way_list r[:json]['route_instructions']
if r[:route]=="w#{i}"
r[:time] = r[:json]['route_summary']['total_time']
r[:distance] = r[:json]['route_summary']['total_distance']
@ -24,7 +24,7 @@ def test_routability_row i
end
result[direction] = r
end
# check if forw and backw returned the same values
result['bothw'] = {}
[:status,:time,:distance,:speed].each do |key|
@ -62,12 +62,12 @@ Then /^routability should be$/ do |table|
else
raise "*** Unknown expectation format: #{want}"
end
if FuzzyMatch.match output_row[direction], want
output_row[direction] = row[direction]
end
end
if output_row != row
log_fail row,output_row,result
end

View File

@ -13,6 +13,6 @@ Feature: Separate settings for forward/backward direction
| abcd | river |
When I route I should get
| from | to | route | distance | speed |
| a | d | abcd | 300 +- 1m | 36 km/h |
| d | a | abcd | 300 +- 1m | 16 km/h |
| from | to | route | distance | speed |
| a | d | abcd | 300 +- 1m | 36 km/h |
| d | a | abcd | 300 +- 1m | 16 km/h +- 1 |

View File

@ -26,6 +26,6 @@ Feature: Testbot - speeds
| ab | river |
When I route I should get
| from | to | route | speed | time | distance |
| a | b | ab | 36 km/h | 10s | 100m |
| b | a | ab | 16 km/h | 22s | 100m |
| from | to | route | speed | time | distance |
| a | b | ab | 36 km/h | 10s | 100m |
| b | a | ab | 16 km/h +- 1 | 23s | 100m |

View File

@ -45,13 +45,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "typedefs.h"
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <luabind/luabind.hpp>
#include <fstream>
#include <istream>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
@ -158,7 +156,7 @@ int main (int argc, char *argv[]) {
omp_set_num_threads( std::min( omp_get_num_procs(), requested_num_threads) );
LogPolicy::GetInstance().Unmute();
std::ifstream restrictionsInstream( restrictions_path.c_str(), std::ios::binary);
boost::filesystem::ifstream restrictionsInstream(restrictions_path, std::ios::binary);
TurnRestriction restriction;
UUID uuid_loaded, uuid_orig;
unsigned usableRestrictionsCounter(0);
@ -180,14 +178,15 @@ int main (int argc, char *argv[]) {
);
restrictionsInstream.close();
std::ifstream in;
in.open (input_path.c_str(), std::ifstream::in | std::ifstream::binary);
boost::filesystem::ifstream in;
in.open(input_path, std::ios::in|std::ios::binary);
std::string nodeOut(input_path.string() + ".nodes");
std::string edgeOut(input_path.string() + ".edges");
std::string graphOut(input_path.string() + ".hsgr");
std::string rtree_nodes_path(input_path.string() + ".ramIndex");
std::string rtree_leafs_path(input_path.string() + ".fileIndex");
const std::string nodeOut = input_path.string() + ".nodes";
const std::string edgeOut = input_path.string() + ".edges";
const std::string geometry_filename = input_path.string() + ".geometry";
const std::string graphOut = input_path.string() + ".hsgr";
const std::string rtree_nodes_path = input_path.string() + ".ramIndex";
const std::string rtree_leafs_path = input_path.string() + ".fileIndex";
/*** Setup Scripting Environment ***/
@ -221,6 +220,7 @@ int main (int argc, char *argv[]) {
return 1;
}
speedProfile.trafficSignalPenalty = 10*lua_tointeger(myLuaState, -1);
SimpleLogger().Write(logDEBUG) << "traffic_signal_penalty: " << speedProfile.trafficSignalPenalty;
if(0 != luaL_dostring( myLuaState, "return u_turn_penalty\n")) {
std::cerr <<
@ -254,23 +254,45 @@ int main (int argc, char *argv[]) {
SimpleLogger().Write() << "Generating edge-expanded graph representation";
EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile);
std::vector<ImportEdge>().swap(edgeList);
edgeBasedGraphFactory->Run(edgeOut.c_str(), myLuaState);
edgeBasedGraphFactory->Run(edgeOut,geometry_filename, myLuaState);
std::vector<TurnRestriction>().swap(inputRestrictions);
std::vector<NodeID>().swap(bollardNodes);
std::vector<NodeID>().swap(trafficLightNodes);
NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
unsigned edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfEdgeBasedNodes();
BOOST_ASSERT(
edgeBasedNodeNumber != std::numeric_limits<unsigned>::max()
);
DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
std::vector<EdgeBasedNode> nodeBasedEdgeList;
edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
delete edgeBasedGraphFactory;
double expansionHasFinishedTime = get_timestamp() - startupTime;
// Building grid-like nearest-neighbor data structure
SimpleLogger().Write() << "building r-tree ...";
StaticRTree<EdgeBasedNode> * rtree =
new StaticRTree<EdgeBasedNode>(
nodeBasedEdgeList,
rtree_nodes_path.c_str(),
rtree_leafs_path.c_str(),
internalToExternalNodeMapping
);
delete rtree;
IteratorbasedCRC32<std::vector<EdgeBasedNode> > crc32;
unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
nodeBasedEdgeList.clear();
std::vector<EdgeBasedNode>(nodeBasedEdgeList).swap(nodeBasedEdgeList);
SimpleLogger().Write() << "CRC32: " << crc32OfNodeBasedEdgeList;
/***
* Writing info on original (node-based) nodes
*/
SimpleLogger().Write() << "writing node map ...";
std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary);
boost::filesystem::ofstream mapOutFile(nodeOut, std::ios::binary);
const unsigned size_of_mapping = internalToExternalNodeMapping.size();
mapOutFile.write((char *)&size_of_mapping, sizeof(unsigned));
mapOutFile.write(
@ -280,26 +302,6 @@ int main (int argc, char *argv[]) {
mapOutFile.close();
std::vector<NodeInfo>().swap(internalToExternalNodeMapping);
double expansionHasFinishedTime = get_timestamp() - startupTime;
/***
* Building grid-like nearest-neighbor data structure
*/
SimpleLogger().Write() << "building r-tree ...";
StaticRTree<EdgeBasedNode> * rtree =
new StaticRTree<EdgeBasedNode>(
nodeBasedEdgeList,
rtree_nodes_path.c_str(),
rtree_leafs_path.c_str()
);
delete rtree;
IteratorbasedCRC32<std::vector<EdgeBasedNode> > crc32;
unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
nodeBasedEdgeList.clear();
std::vector<EdgeBasedNode>(nodeBasedEdgeList).swap(nodeBasedEdgeList);
SimpleLogger().Write() << "CRC32: " << crc32OfNodeBasedEdgeList;
/***
* Contracting the edge-expanded graph
*/
@ -323,86 +325,99 @@ int main (int argc, char *argv[]) {
*/
std::sort(contractedEdgeList.begin(), contractedEdgeList.end());
unsigned numberOfNodes = 0;
unsigned numberOfEdges = contractedEdgeList.size();
unsigned max_used_node_id = 0;
unsigned contracted_edge_count = contractedEdgeList.size();
SimpleLogger().Write() <<
"Serializing compacted graph of " <<
numberOfEdges <<
contracted_edge_count <<
" edges";
std::ofstream hsgr_output_stream(graphOut.c_str(), std::ios::binary);
boost::filesystem::ofstream hsgr_output_stream(graphOut, std::ios::binary);
hsgr_output_stream.write((char*)&uuid_orig, sizeof(UUID) );
BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) {
BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList)
{
BOOST_ASSERT( UINT_MAX != edge.source );
BOOST_ASSERT( UINT_MAX != edge.target );
if(edge.source > numberOfNodes) {
numberOfNodes = edge.source;
}
if(edge.target > numberOfNodes) {
numberOfNodes = edge.target;
}
max_used_node_id = std::max(max_used_node_id, edge.source);
max_used_node_id = std::max(max_used_node_id, edge.target);
SimpleLogger().Write(logDEBUG) << "generated edge (" << edge.source << ", " << edge.target << ")=" << edge.data.distance;
}
numberOfNodes+=1;
SimpleLogger().Write(logDEBUG) << "input graph has " << edgeBasedNodeNumber << " nodes";
SimpleLogger().Write(logDEBUG) << "contracted graph has " << max_used_node_id << " nodes";
max_used_node_id+=1;
std::vector< StaticGraph<EdgeData>::_StrNode > _nodes;
_nodes.resize( numberOfNodes + 1 );
std::vector< StaticGraph<EdgeData>::_StrNode > node_array;
node_array.resize( edgeBasedNodeNumber + 1);
SimpleLogger().Write() << "Building node array";
StaticGraph<EdgeData>::EdgeIterator edge = 0;
StaticGraph<EdgeData>::EdgeIterator position = 0;
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < max_used_node_id; ++node)
{
lastEdge = edge;
while ((edge < contracted_edge_count) && (contractedEdgeList[edge].source == node))
{
++edge;
_nodes[node].firstEdge = position; //=edge
}
node_array[node].firstEdge = position; //=edge
position += edge - lastEdge; //remove
}
_nodes.back().firstEdge = numberOfEdges; //sentinel element
++numberOfNodes;
BOOST_ASSERT_MSG(
_nodes.size() == numberOfNodes,
"no. of nodes dont match"
);
for (unsigned sentinel_counter = max_used_node_id;
sentinel_counter != node_array.size();
++sentinel_counter
)
{
//sentinel element, guarded against underflow
node_array[sentinel_counter].firstEdge = contracted_edge_count;
}
unsigned node_array_size = node_array.size();
//serialize crc32, aka checksum
hsgr_output_stream.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
//serialize number f nodes
hsgr_output_stream.write((char*) &numberOfNodes, sizeof(unsigned));
//serialize number of nodes
hsgr_output_stream.write((char*) &node_array_size, sizeof(unsigned));
//serialize number of edges
hsgr_output_stream.write((char*) &position, sizeof(unsigned));
hsgr_output_stream.write((char*) &contracted_edge_count, sizeof(unsigned));
//serialize all nodes
hsgr_output_stream.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
hsgr_output_stream.write((char*) &node_array[0], sizeof(StaticGraph<EdgeData>::_StrNode)*node_array_size);
//serialize all edges
--numberOfNodes;
SimpleLogger().Write() << "Building edge array";
edge = 0;
int usedEdgeCounter = 0;
SimpleLogger().Write() << "Building Node Array";
StaticGraph<EdgeData>::_StrEdge currentEdge;
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
for ( StaticGraph<EdgeData>::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
assert(node != contractedEdgeList[edge].target);
currentEdge.target = contractedEdgeList[edge].target;
currentEdge.data = contractedEdgeList[edge].data;
if(currentEdge.data.distance <= 0) {
SimpleLogger().Write(logWARNING) <<
"Edge: " << i <<
",source: " << contractedEdgeList[edge].source <<
", target: " << contractedEdgeList[edge].target <<
", dist: " << currentEdge.data.distance;
SimpleLogger().Write(logWARNING) <<
"Failed at edges of node " << node <<
" of " << numberOfNodes;
return 1;
}
//Serialize edges
hsgr_output_stream.write((char*) &currentEdge, sizeof(StaticGraph<EdgeData>::_StrEdge));
++edge;
++usedEdgeCounter;
StaticGraph<EdgeData>::_StrEdge currentEdge;
for (unsigned edge = 0; edge < contractedEdgeList.size(); ++edge)
{
// no eigen loops
BOOST_ASSERT(contractedEdgeList[edge].source != contractedEdgeList[edge].target);
currentEdge.target = contractedEdgeList[edge].target;
currentEdge.data = contractedEdgeList[edge].data;
// every target needs to be valid
BOOST_ASSERT(currentEdge.target < max_used_node_id);
if(currentEdge.data.distance <= 0) {
SimpleLogger().Write(logWARNING) <<
"Edge: " << edge <<
",source: " << contractedEdgeList[edge].source <<
", target: " << contractedEdgeList[edge].target <<
", dist: " << currentEdge.data.distance;
SimpleLogger().Write(logWARNING) <<
"Failed at adjacency list of node " << contractedEdgeList[edge].source << "/" << node_array.size()-1;
return 1;
}
hsgr_output_stream.write((char*) &currentEdge, sizeof(StaticGraph<EdgeData>::_StrEdge));
++usedEdgeCounter;
}
hsgr_output_stream.close();
SimpleLogger().Write() << "Preprocessing : " <<
(get_timestamp() - startupTime) << " seconds";
SimpleLogger().Write() << "Expansion : " <<
@ -413,19 +428,16 @@ int main (int argc, char *argv[]) {
(edgeBasedNodeNumber/contraction_duration) << " nodes/sec and " <<
usedEdgeCounter/contraction_duration << " edges/sec";
hsgr_output_stream.close();
//cleanedEdgeList.clear();
_nodes.clear();
node_array.clear();
SimpleLogger().Write() << "finished preprocessing";
} catch(boost::program_options::too_many_positional_options_error& e) {
} catch(boost::program_options::too_many_positional_options_error&) {
SimpleLogger().Write(logWARNING) << "Only one file can be specified";
return 1;
} catch(boost::program_options::error& e) {
SimpleLogger().Write(logWARNING) << e.what();
return 1;
} catch ( const std::exception &e ) {
SimpleLogger().Write(logWARNING) <<
"Exception occured: " << e.what() << std::endl;
SimpleLogger().Write(logWARNING) << "Exception occured: " << e.what() << std::endl;
return 1;
}
return 0;

View File

@ -96,6 +96,22 @@ turn_penalty = 60
turn_bias = 1.4
-- End of globals
local function parse_maxspeed(source)
if not source then
return 0
end
local n = tonumber(source:match("%d*"))
if not n then
n = 0
end
if string.match(source, "mph") or string.match(source, "mp/h") then
n = (n*1609)/1000;
end
return n
end
function get_exceptions(vector)
for i,v in ipairs(restriction_exception_tags) do
vector:Add(v)
@ -107,27 +123,27 @@ function node_function (node)
local access = Access.find_access_tag(node, access_tags_hierachy)
local traffic_signal = node.tags:Find("highway")
-- flag node if it carries a traffic light
if traffic_signal == "traffic_signals" then
node.traffic_light = true
end
-- flag node if it carries a traffic light
if traffic_signal == "traffic_signals" then
node.traffic_light = true
end
-- parse access and barrier tags
if access and access ~= "" then
if access_tag_blacklist[access] then
node.bollard = true
else
node.bollard = false
end
elseif barrier and barrier ~= "" then
if barrier_whitelist[barrier] then
node.bollard = false
else
node.bollard = true
end
end
-- parse access and barrier tags
if access and access ~= "" then
if access_tag_blacklist[access] then
node.bollard = true
else
node.bollard = false
end
elseif barrier and barrier ~= "" then
if barrier_whitelist[barrier] then
node.bollard = false
else
node.bollard = true
end
end
return 1
-- return 1
end
function way_function (way)
@ -159,14 +175,13 @@ function way_function (way)
return 0
end
-- other tags
local name = way.tags:Find("name")
local ref = way.tags:Find("ref")
local junction = way.tags:Find("junction")
local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") )
local maxspeed_forward = parseMaxspeed(way.tags:Find( "maxspeed:forward"))
local maxspeed_backward = parseMaxspeed(way.tags:Find( "maxspeed:backward"))
local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") )
local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward"))
local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
local barrier = way.tags:Find("barrier")
local oneway = way.tags:Find("oneway")
local onewayClass = way.tags:Find("oneway:bicycle")
@ -305,7 +320,6 @@ function way_function (way)
end
end
-- cycleways
if cycleway and cycleway_tags[cycleway] then
way.speed = bicycle_speeds["cycleway"]

View File

@ -32,7 +32,7 @@ speed_profile = {
["default"] = 10
}
local take_minimum_of_speeds = false
local take_minimum_of_speeds = false
local obey_oneway = true
local obey_bollards = true
local use_turn_restrictions = true
@ -77,6 +77,14 @@ local function parse_maxspeed(source)
return n
end
-- function turn_function (angle)
-- -- print ("called at angle " .. angle )
-- local index = math.abs(math.floor(angle/10+0.5))+1 -- +1 'coz LUA starts as idx 1
-- local penalty = turn_cost_table[index]
-- -- print ("index: " .. index .. ", bias: " .. penalty )
-- return penalty
-- end
function node_function (node)
local access = find_access_tag(node, access_tags_hierachy)
@ -260,4 +268,4 @@ function node_vector_function(vector)
for v in vector.nodes do
node_function(v)
end
end
end

View File

@ -108,6 +108,7 @@ int main (int argc, const char * argv[])
SimpleLogger().Write() << "HSGR file:\t" << server_paths["hsgrdata"];
SimpleLogger().Write(logDEBUG) << "Nodes file:\t" << server_paths["nodesdata"];
SimpleLogger().Write(logDEBUG) << "Edges file:\t" << server_paths["edgesdata"];
SimpleLogger().Write(logDEBUG) << "Geometry file:\t" << server_paths["geometries"];
SimpleLogger().Write(logDEBUG) << "RAM file:\t" << server_paths["ramindex"];
SimpleLogger().Write(logDEBUG) << "Index file:\t" << server_paths["fileindex"];
SimpleLogger().Write(logDEBUG) << "Names file:\t" << server_paths["namesdata"];

View File

@ -28,9 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef TYPEDEFS_H_
#define TYPEDEFS_H_
// To fix long and long long woes
#include <boost/integer.hpp>
#include <boost/integer_traits.hpp>
#include <limits>
// Necessary workaround for Windows as VS doesn't implement C99
#ifdef _MSC_VER
@ -46,9 +44,10 @@ digitT round(digitT x) {
typedef unsigned int NodeID;
typedef unsigned int EdgeID;
typedef unsigned int EdgeWeight;
typedef int EdgeWeight;
static const NodeID SPECIAL_NODEID = boost::integer_traits<uint32_t>::const_max;
static const EdgeID SPECIAL_EDGEID = boost::integer_traits<uint32_t>::const_max;
static const NodeID SPECIAL_NODEID = std::numeric_limits<unsigned>::max();
static const EdgeID SPECIAL_EDGEID = std::numeric_limits<unsigned>::max();
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<int>::max();
#endif /* TYPEDEFS_H_ */