Split RestrictionMap and NodeBasedGraph from EdgeBasedGraphFactory
First step in an effort to simplify EdgeBasedGraphFactory.
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
#ifndef __NODE_BASED_GRAPH_H__
|
||||
#define __NODE_BASED_GRAPH_H__
|
||||
|
||||
#include "DynamicGraph.h"
|
||||
#include "ImportEdge.h"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
struct NodeBasedEdgeData {
|
||||
NodeBasedEdgeData() : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), nameID(std::numeric_limits<unsigned>::max()),
|
||||
type(std::numeric_limits<short>::max()), isAccessRestricted(false), shortcut(false), forward(false), backward(false),
|
||||
roundabout(false), ignore_in_grid(false), contraFlow(false)
|
||||
{ }
|
||||
|
||||
int distance;
|
||||
unsigned edgeBasedNodeID;
|
||||
unsigned nameID;
|
||||
short type;
|
||||
bool isAccessRestricted:1;
|
||||
bool shortcut:1;
|
||||
bool forward:1;
|
||||
bool backward:1;
|
||||
bool roundabout: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);
|
||||
}
|
||||
};
|
||||
|
||||
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||
|
||||
// Factory method to create NodeBasedDynamicGraph from ImportEdges
|
||||
inline boost::shared_ptr<NodeBasedDynamicGraph> NodeBasedDynamicGraphFromImportEdges(
|
||||
int number_of_nodes,
|
||||
std::vector<ImportEdge>& input_edge_list
|
||||
) {
|
||||
typedef NodeBasedDynamicGraph::InputEdge DynInputEdge;
|
||||
|
||||
std::sort( input_edge_list.begin(), input_edge_list.end() );
|
||||
|
||||
//TODO: remove duplicate edges
|
||||
DeallocatingVector<DynInputEdge> edges_list;
|
||||
DynInputEdge edge;
|
||||
for(const ImportEdge& import_edge : input_edge_list) {
|
||||
|
||||
if( !import_edge.isForward() ) {
|
||||
edge.source = import_edge.target();
|
||||
edge.target = import_edge.source();
|
||||
edge.data.backward = import_edge.isForward();
|
||||
edge.data.forward = import_edge.isBackward();
|
||||
} else {
|
||||
edge.source = import_edge.source();
|
||||
edge.target = import_edge.target();
|
||||
edge.data.forward = import_edge.isForward();
|
||||
edge.data.backward = import_edge.isBackward();
|
||||
}
|
||||
|
||||
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.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.contraFlow = import_edge.isContraFlow();
|
||||
edges_list.push_back( edge );
|
||||
|
||||
if( !import_edge.IsSplit() ) {
|
||||
using std::swap; //enable ADL
|
||||
swap( edge.source, edge.target );
|
||||
edge.data.SwapDirectionFlags();
|
||||
edges_list.push_back( edge );
|
||||
}
|
||||
}
|
||||
|
||||
std::sort( edges_list.begin(), edges_list.end() );
|
||||
auto graph = boost::make_shared<NodeBasedDynamicGraph>(
|
||||
number_of_nodes,
|
||||
edges_list
|
||||
);
|
||||
|
||||
//FIXME probably unneeded since this is the end of scope
|
||||
DeallocatingVector<DynInputEdge>().swap(edges_list);
|
||||
BOOST_ASSERT(0 == edges_list.size() );
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#include "RestrictionMap.h"
|
||||
#include "NodeBasedGraph.h"
|
||||
|
||||
RestrictionMap::RestrictionMap(const boost::shared_ptr<NodeBasedDynamicGraph>& graph, const std::vector<TurnRestriction> & input_restrictions_list)
|
||||
: m_count(0)
|
||||
, m_graph(graph)
|
||||
{
|
||||
// decompose restirction consisting of a start, via and end note into a start-edge
|
||||
// and all end-nodes
|
||||
for (auto& restriction : input_restrictions_list) {
|
||||
std::pair<NodeID, NodeID> restriction_source =
|
||||
std::make_pair(restriction.fromNode, restriction.viaNode);
|
||||
unsigned index;
|
||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if(restriction_iter == m_restriction_map.end()) {
|
||||
index = m_restriction_bucket_list.size();
|
||||
m_restriction_bucket_list.resize(index+1);
|
||||
m_restriction_map.emplace(restriction_source, index);
|
||||
} else {
|
||||
index = restriction_iter->second;
|
||||
//Map already contains an is_only_*-restriction
|
||||
if(m_restriction_bucket_list.at(index).begin()->second) {
|
||||
continue;
|
||||
} else if(restriction.flags.isOnly) {
|
||||
//We are going to insert an is_only_*-restriction. There can be only one.
|
||||
m_count -= m_restriction_bucket_list.at(index).size();
|
||||
m_restriction_bucket_list.at(index).clear();
|
||||
}
|
||||
}
|
||||
++m_count;
|
||||
m_restriction_bucket_list.at(index).push_back(
|
||||
std::make_pair( restriction.toNode, restriction.flags.isOnly)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace end v with w in each turn restriction containing u as via node
|
||||
*
|
||||
* Note: We need access to node based graph.
|
||||
*/
|
||||
void RestrictionMap::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() );
|
||||
|
||||
// find all possible start edges
|
||||
// it is more efficent to get a (small) list of potential start edges
|
||||
// than iterating over all buckets
|
||||
std::vector<NodeID> predecessors;
|
||||
for(
|
||||
EdgeID current_edge_id = m_graph->BeginEdges(u);
|
||||
current_edge_id < m_graph->EndEdges(u);
|
||||
++current_edge_id
|
||||
) {
|
||||
const EdgeData & edge_data = m_graph->GetEdgeData(current_edge_id);
|
||||
const NodeID target = m_graph->GetTarget(current_edge_id);
|
||||
if( edge_data.backward && ( v != target) ) {
|
||||
predecessors.push_back(target);
|
||||
}
|
||||
}
|
||||
|
||||
for(const NodeID x : predecessors) {
|
||||
const std::pair<NodeID, NodeID> restr_start = std::make_pair(x,u);
|
||||
auto restriction_iterator = m_restriction_map.find( restr_start );
|
||||
if( restriction_iterator == m_restriction_map.end() )
|
||||
continue;
|
||||
|
||||
const unsigned index = restriction_iterator->second;
|
||||
auto& bucket = m_restriction_bucket_list.at(index);
|
||||
for(RestrictionTarget& restriction_target : bucket) {
|
||||
if( v == restriction_target.first ) {
|
||||
restriction_target.first = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the start edge (v, w) with (u, w), only start node changes.
|
||||
*/
|
||||
void RestrictionMap::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);
|
||||
|
||||
auto 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) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the edge (u, v) is contained in any turn restriction.
|
||||
* If so returns id of first target node.
|
||||
*/
|
||||
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(
|
||||
const NodeID u,
|
||||
const NodeID v
|
||||
) const {
|
||||
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);
|
||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||
|
||||
if (restriction_iter != m_restriction_map.end()) {
|
||||
const unsigned index = restriction_iter->second;
|
||||
auto& bucket = m_restriction_bucket_list.at(index);
|
||||
for(const RestrictionSource& restriction_target : bucket) {
|
||||
if(restriction_target.second) {
|
||||
return restriction_target.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the turn described by start u, via v and targed w is covert by any turn restriction.
|
||||
*/
|
||||
bool RestrictionMap::CheckIfTurnIsRestricted(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
) const {
|
||||
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);
|
||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||
|
||||
if (restriction_iter != m_restriction_map.end()) {
|
||||
const unsigned index = restriction_iter->second;
|
||||
auto& bucket = m_restriction_bucket_list.at(index);
|
||||
for(const RestrictionTarget & restriction_target : bucket) {
|
||||
if(
|
||||
( w == restriction_target.first ) && // target found
|
||||
( !restriction_target.second ) // and not an only_-restr.
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __RESTRICTION_MAP_H__
|
||||
#define __RESTRICTION_MAP_H__
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "DynamicGraph.h"
|
||||
#include "Restriction.h"
|
||||
#include "NodeBasedGraph.h"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
/*!
|
||||
* Makee it efficent to look up if an edge is the start + via node of a TurnRestriction.
|
||||
* Is needed by EdgeBasedGraphFactory.
|
||||
*/
|
||||
class RestrictionMap
|
||||
{
|
||||
public:
|
||||
RestrictionMap(const boost::shared_ptr<NodeBasedDynamicGraph>& graph,
|
||||
const std::vector<TurnRestriction> & input_restrictions_list);
|
||||
|
||||
void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
|
||||
void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
|
||||
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
||||
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
||||
|
||||
unsigned size() { return m_count; }
|
||||
|
||||
private:
|
||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||
typedef std::pair<NodeID, bool> RestrictionTarget;
|
||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
||||
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
||||
|
||||
unsigned m_count;
|
||||
boost::shared_ptr<NodeBasedDynamicGraph> m_graph;
|
||||
//! index -> list of (target, isOnly)
|
||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||
//! maps (start, via) -> bucket index
|
||||
boost::unordered_map<RestrictionSource, unsigned> m_restriction_map;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user