Refactoring StronglyConnectedComponents.h
This commit is contained in:
parent
dabc9589e9
commit
e1620b8fa2
@ -35,11 +35,13 @@ Strongly connected components using Tarjan's Algorithm
|
|||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/integer.hpp>
|
#include <boost/integer.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
#include <boost/unordered_set.hpp>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <gdal.h>
|
#include <gdal.h>
|
||||||
@ -48,7 +50,7 @@ Strongly connected components using Tarjan's Algorithm
|
|||||||
#include <gdal/gdal.h>
|
#include <gdal/gdal.h>
|
||||||
#include <gdal/ogrsf_frmts.h>
|
#include <gdal/ogrsf_frmts.h>
|
||||||
#endif
|
#endif
|
||||||
#include <cassert>
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -64,7 +66,6 @@ private:
|
|||||||
|
|
||||||
struct TarjanEdgeData {
|
struct TarjanEdgeData {
|
||||||
int distance;
|
int distance;
|
||||||
unsigned edgeBasedNodeID;
|
|
||||||
unsigned nameID:31;
|
unsigned nameID:31;
|
||||||
bool shortcut:1;
|
bool shortcut:1;
|
||||||
short type;
|
short type;
|
||||||
@ -77,26 +78,28 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TarjanStackFrame {
|
struct TarjanStackFrame {
|
||||||
explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
|
explicit TarjanStackFrame(
|
||||||
|
NodeID v,
|
||||||
|
NodeID parent
|
||||||
|
) : v(v), parent(parent) { }
|
||||||
NodeID v;
|
NodeID v;
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
|
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
|
||||||
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
|
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||||
typedef std::pair<NodeID, bool> RestrictionTarget;
|
typedef std::pair<NodeID, bool> restriction_target;
|
||||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
||||||
|
|
||||||
std::vector<NodeInfo> inputNodeInfoList;
|
std::vector<NodeInfo> m_coordinate_list;
|
||||||
unsigned numberOfTurnRestrictions;
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
boost::shared_ptr<TarjanDynamicGraph> _nodeBasedGraph;
|
boost::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
|
||||||
boost::unordered_map<NodeID, bool> _barrierNodes;
|
boost::unordered_set<NodeID> m_barrier_node_list;
|
||||||
boost::unordered_map<NodeID, bool> _trafficLights;
|
boost::unordered_set<NodeID> m_traffic_light_list;
|
||||||
|
unsigned m_restriction_counter;
|
||||||
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
|
RestrictionMap m_restriction_map;
|
||||||
RestrictionMap _restrictionMap;
|
|
||||||
|
|
||||||
struct EdgeBasedNode {
|
struct EdgeBasedNode {
|
||||||
bool operator<(const EdgeBasedNode & other) const {
|
bool operator<(const EdgeBasedNode & other) const {
|
||||||
@ -116,93 +119,99 @@ private:
|
|||||||
bool ignoreInGrid:1;
|
bool ignoreInGrid:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
|
|
||||||
public:
|
public:
|
||||||
TarjanSCC(
|
TarjanSCC(
|
||||||
int nodes,
|
int number_of_nodes,
|
||||||
std::vector<NodeBasedEdge> & inputEdges,
|
std::vector<NodeBasedEdge> & input_edges,
|
||||||
std::vector<NodeID> & bn,
|
std::vector<NodeID> & bn,
|
||||||
std::vector<NodeID> & tl,
|
std::vector<NodeID> & tl,
|
||||||
std::vector<TurnRestriction> & irs,
|
std::vector<TurnRestriction> & irs,
|
||||||
std::vector<NodeInfo> & nI
|
std::vector<NodeInfo> & nI
|
||||||
) :
|
) :
|
||||||
inputNodeInfoList(nI),
|
m_coordinate_list(nI),
|
||||||
numberOfTurnRestrictions(irs.size())
|
m_restriction_counter(irs.size())
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const TurnRestriction & restriction, irs) {
|
BOOST_FOREACH(const TurnRestriction & restriction, irs) {
|
||||||
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
|
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
|
||||||
restriction.fromNode, restriction.viaNode
|
restriction.fromNode, restriction.viaNode
|
||||||
);
|
);
|
||||||
unsigned index;
|
unsigned index;
|
||||||
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::iterator restriction_iterator = m_restriction_map.find(restrictionSource);
|
||||||
if(restrIter == _restrictionMap.end()) {
|
if(restriction_iterator == m_restriction_map.end()) {
|
||||||
index = _restrictionBucketVector.size();
|
index = m_restriction_bucket_list.size();
|
||||||
_restrictionBucketVector.resize(index+1);
|
m_restriction_bucket_list.resize(index+1);
|
||||||
_restrictionMap[restrictionSource] = index;
|
m_restriction_map[restrictionSource] = index;
|
||||||
} else {
|
} else {
|
||||||
index = restrIter->second;
|
index = restriction_iterator->second;
|
||||||
//Map already contains an is_only_*-restriction
|
//Map already contains an is_only_*-restriction
|
||||||
if(_restrictionBucketVector.at(index).begin()->second)
|
if(m_restriction_bucket_list.at(index).begin()->second) {
|
||||||
continue;
|
continue;
|
||||||
else if(restriction.flags.isOnly){
|
} else if(restriction.flags.isOnly) {
|
||||||
//We are going to insert an is_only_*-restriction. There can be only one.
|
//We are going to insert an is_only_*-restriction. There can be only one.
|
||||||
_restrictionBucketVector.at(index).clear();
|
m_restriction_bucket_list.at(index).clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_restrictionBucketVector.at(index).push_back(
|
m_restriction_bucket_list.at(index).push_back(
|
||||||
std::make_pair(restriction.toNode, restriction.flags.isOnly)
|
std::make_pair(restriction.toNode, restriction.flags.isOnly)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(NodeID id, bn) {
|
m_barrier_node_list.insert(bn.begin(), bn.end());
|
||||||
_barrierNodes[id] = true;
|
m_traffic_light_list.insert(tl.begin(), tl.end());
|
||||||
}
|
|
||||||
BOOST_FOREACH(NodeID id, tl) {
|
|
||||||
_trafficLights[id] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeallocatingVector< TarjanEdge > edges;
|
|
||||||
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
|
|
||||||
|
|
||||||
|
DeallocatingVector< TarjanEdge > edge_list;
|
||||||
|
BOOST_FOREACH(const NodeBasedEdge & input_edge, input_edges) {
|
||||||
TarjanEdge edge;
|
TarjanEdge edge;
|
||||||
if(!i->isForward()) {
|
if(!input_edge.isForward()) {
|
||||||
edge.source = i->target();
|
edge.source = input_edge.target();
|
||||||
edge.target = i->source();
|
edge.target = input_edge.source();
|
||||||
edge.data.backward = i->isForward();
|
edge.data.backward = input_edge.isForward();
|
||||||
edge.data.forward = i->isBackward();
|
edge.data.forward = input_edge.isBackward();
|
||||||
} else {
|
} else {
|
||||||
edge.source = i->source();
|
edge.source = input_edge.source();
|
||||||
edge.target = i->target();
|
edge.target = input_edge.target();
|
||||||
edge.data.forward = i->isForward();
|
edge.data.forward = input_edge.isForward();
|
||||||
edge.data.backward = i->isBackward();
|
edge.data.backward = input_edge.isBackward();
|
||||||
}
|
}
|
||||||
if(edge.source == edge.target)
|
if(edge.source == edge.target) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
edge.data.distance = (std::max)((int)i->weight(), 1 );
|
edge.data.distance = (std::max)((int)input_edge.weight(), 1 );
|
||||||
assert( edge.data.distance > 0 );
|
BOOST_ASSERT( edge.data.distance > 0 );
|
||||||
edge.data.shortcut = false;
|
edge.data.shortcut = false;
|
||||||
edge.data.roundabout = i->isRoundabout();
|
edge.data.roundabout = input_edge.isRoundabout();
|
||||||
edge.data.ignoreInGrid = i->ignoreInGrid();
|
edge.data.ignoreInGrid = input_edge.ignoreInGrid();
|
||||||
edge.data.nameID = i->name();
|
edge.data.nameID = input_edge.name();
|
||||||
edge.data.type = i->type();
|
edge.data.type = input_edge.type();
|
||||||
edge.data.isAccessRestricted = i->isAccessRestricted();
|
edge.data.isAccessRestricted = input_edge.isAccessRestricted();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
|
||||||
edge.data.reversedEdge = false;
|
edge.data.reversedEdge = false;
|
||||||
edges.push_back( edge );
|
edge_list.push_back( edge );
|
||||||
if( edge.data.backward ) {
|
if( edge.data.backward ) {
|
||||||
std::swap( edge.source, edge.target );
|
std::swap( edge.source, edge.target );
|
||||||
edge.data.forward = i->isBackward();
|
edge.data.forward = input_edge.isBackward();
|
||||||
edge.data.backward = i->isForward();
|
edge.data.backward = input_edge.isForward();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
|
||||||
edge.data.reversedEdge = true;
|
edge.data.reversedEdge = true;
|
||||||
edges.push_back( edge );
|
edge_list.push_back( edge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeBasedEdge>().swap(inputEdges);
|
std::vector<NodeBasedEdge>().swap(input_edges);
|
||||||
std::sort( edges.begin(), edges.end() );
|
BOOST_ASSERT_MSG(
|
||||||
_nodeBasedGraph = boost::make_shared<TarjanDynamicGraph>( nodes, edges );
|
0 == input_edges.size() && 0 == input_edges.capacity(),
|
||||||
|
"input edge vector not properly deallocated"
|
||||||
|
);
|
||||||
|
|
||||||
|
std::sort( edge_list.begin(), edge_list.end() );
|
||||||
|
|
||||||
|
m_node_based_graph = boost::make_shared<TarjanDynamicGraph>(
|
||||||
|
number_of_nodes,
|
||||||
|
edge_list
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
~TarjanSCC() {
|
||||||
|
m_node_based_graph.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run() {
|
void Run() {
|
||||||
@ -211,162 +220,203 @@ public:
|
|||||||
DeleteFileIfExists("component.shx");
|
DeleteFileIfExists("component.shx");
|
||||||
DeleteFileIfExists("component.shp");
|
DeleteFileIfExists("component.shp");
|
||||||
|
|
||||||
Percent p(_nodeBasedGraph->GetNumberOfNodes());
|
Percent p(m_node_based_graph->GetNumberOfNodes());
|
||||||
|
|
||||||
const char *pszDriverName = "ESRI Shapefile";
|
|
||||||
OGRSFDriver *poDriver;
|
|
||||||
|
|
||||||
OGRRegisterAll();
|
OGRRegisterAll();
|
||||||
|
|
||||||
poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(
|
const char *pszDriverName = "ESRI Shapefile";
|
||||||
pszDriverName );
|
OGRSFDriver * poDriver = OGRSFDriverRegistrar::GetRegistrar()->
|
||||||
if( poDriver == NULL )
|
GetDriverByName( pszDriverName );
|
||||||
{
|
if( NULL == poDriver ) {
|
||||||
printf( "%s driver not available.\n", pszDriverName );
|
throw OSRMException("ESRI Shapefile driver not available");
|
||||||
exit( 1 );
|
|
||||||
}
|
}
|
||||||
OGRDataSource *poDS;
|
OGRDataSource * poDS = poDriver->CreateDataSource(
|
||||||
|
"component.shp",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
poDS = poDriver->CreateDataSource( "component.shp", NULL );
|
if( NULL == poDS ) {
|
||||||
if( poDS == NULL ) {
|
throw OSRMException("Creation of output file failed");
|
||||||
printf( "Creation of output file failed.\n" );
|
|
||||||
exit( 1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OGRLayer *poLayer;
|
OGRLayer * poLayer = poDS->CreateLayer(
|
||||||
|
"component",
|
||||||
|
NULL,
|
||||||
|
wkbLineString,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
poLayer = poDS->CreateLayer( "component", NULL, wkbLineString, NULL );
|
if( NULL == poLayer ) {
|
||||||
if( poLayer == NULL ) {
|
throw OSRMException("Layer creation failed.");
|
||||||
printf( "Layer creation failed.\n" );
|
|
||||||
exit( 1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//The following is a hack to distinguish between stuff that happens
|
||||||
//The following is a hack to distinguish between stuff that happens before the recursive call and stuff that happens after
|
//before the recursive call and stuff that happens after
|
||||||
std::stack<std::pair<bool, TarjanStackFrame> > recursionStack; //true = stuff before, false = stuff after call
|
std::stack<std::pair<bool, TarjanStackFrame> > recursion_stack;
|
||||||
std::stack<NodeID> tarjanStack;
|
//true = stuff before, false = stuff after call
|
||||||
std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
|
std::stack<NodeID> tarjan_stack;
|
||||||
std::vector<NodeID> vectorOfComponentSizes;
|
std::vector<unsigned> components_index(
|
||||||
std::vector<TarjanNode> tarjanNodes(_nodeBasedGraph->GetNumberOfNodes());
|
m_node_based_graph->GetNumberOfNodes(),
|
||||||
unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
|
UINT_MAX
|
||||||
|
);
|
||||||
|
std::vector<NodeID> component_size_vector;
|
||||||
|
std::vector<TarjanNode> tarjan_node_list(
|
||||||
|
m_node_based_graph->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
unsigned component_index = 0, size_of_current_component = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
|
for(
|
||||||
if(UINT_MAX == componentsIndex[node]) {
|
NodeID node = 0, last_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
recursionStack.push(std::make_pair(true, TarjanStackFrame(node,node)) );
|
node < last_node;
|
||||||
|
++node
|
||||||
|
) {
|
||||||
|
if(UINT_MAX == components_index[node]) {
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(true, TarjanStackFrame(node,node))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!recursionStack.empty()) {
|
while(!recursion_stack.empty()) {
|
||||||
bool beforeRecursion = recursionStack.top().first;
|
bool before_recursion = recursion_stack.top().first;
|
||||||
TarjanStackFrame currentFrame = recursionStack.top().second;
|
TarjanStackFrame currentFrame = recursion_stack.top().second;
|
||||||
NodeID v = currentFrame.v;
|
NodeID v = currentFrame.v;
|
||||||
// SimpleLogger().Write() << "popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion";
|
recursion_stack.pop();
|
||||||
recursionStack.pop();
|
|
||||||
|
|
||||||
if(beforeRecursion) {
|
if(before_recursion) {
|
||||||
//Mark frame to handle tail of recursion
|
//Mark frame to handle tail of recursion
|
||||||
recursionStack.push(std::make_pair(false, currentFrame));
|
recursion_stack.push(std::make_pair(false, currentFrame));
|
||||||
|
|
||||||
//Mark essential information for SCC
|
//Mark essential information for SCC
|
||||||
tarjanNodes[v].index = index;
|
tarjan_node_list[v].index = index;
|
||||||
tarjanNodes[v].lowlink = index;
|
tarjan_node_list[v].lowlink = index;
|
||||||
tarjanStack.push(v);
|
tarjan_stack.push(v);
|
||||||
tarjanNodes[v].onStack = true;
|
tarjan_node_list[v].onStack = true;
|
||||||
++index;
|
++index;
|
||||||
// SimpleLogger().Write() << "pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink;
|
|
||||||
|
|
||||||
//Traverse outgoing edges
|
//Traverse outgoing edges
|
||||||
for(TarjanDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
|
for(
|
||||||
TarjanDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2);
|
TarjanDynamicGraph::EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
|
||||||
// SimpleLogger().Write() << "traversing edge (" << v << "," << vprime << ")";
|
e2 < m_node_based_graph->EndEdges(v);
|
||||||
if(UINT_MAX == tarjanNodes[vprime].index) {
|
++e2
|
||||||
|
) {
|
||||||
recursionStack.push(std::make_pair(true,TarjanStackFrame(vprime, v)));
|
const TarjanDynamicGraph::NodeIterator vprime =
|
||||||
|
m_node_based_graph->GetTarget(e2);
|
||||||
|
if(UINT_MAX == tarjan_node_list[vprime].index) {
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(
|
||||||
|
true,
|
||||||
|
TarjanStackFrame(vprime, v)
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// SimpleLogger().Write() << "Node " << vprime << " is already explored";
|
if(
|
||||||
if(tarjanNodes[vprime].onStack) {
|
tarjan_node_list[vprime].onStack &&
|
||||||
unsigned newLowlink = std::min(tarjanNodes[v].lowlink, tarjanNodes[vprime].index);
|
tarjan_node_list[vprime].index < tarjan_node_list[v].lowlink
|
||||||
// SimpleLogger().Write() << "Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink;
|
) {
|
||||||
tarjanNodes[v].lowlink = newLowlink;
|
tarjan_node_list[v].lowlink = tarjan_node_list[vprime].index;
|
||||||
// } else {
|
|
||||||
// SimpleLogger().Write() << "But node " << vprime << " is not on stack";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
tarjan_node_list[currentFrame.parent].lowlink =
|
||||||
// SimpleLogger().Write() << "we are at the end of recursion and checking node " << v;
|
std::min(
|
||||||
{ // setting lowlink in its own scope so it does not pollute namespace
|
tarjan_node_list[currentFrame.parent].lowlink,
|
||||||
// NodeID parent = (UINT_MAX == tarjanNodes[v].parent ? v : tarjanNodes[v].parent );
|
tarjan_node_list[v].lowlink
|
||||||
// SimpleLogger().Write() << "parent=" << currentFrame.parent;
|
);
|
||||||
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
|
|
||||||
//Note the index shift by 1 compared to the recursive version
|
|
||||||
tarjanNodes[currentFrame.parent].lowlink = std::min(tarjanNodes[currentFrame.parent].lowlink, tarjanNodes[v].lowlink);
|
|
||||||
// SimpleLogger().Write() << "Setting tarjanNodes[" << currentFrame.parent <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
|
|
||||||
}
|
|
||||||
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v << "].index=" << tarjanNodes[v].index;
|
|
||||||
|
|
||||||
//after recursion, lets do cycle checking
|
//after recursion, lets do cycle checking
|
||||||
//Check if we found a cycle. This is the bottom part of the recursion
|
//Check if we found a cycle. This is the bottom part of the recursion
|
||||||
if(tarjanNodes[v].lowlink == tarjanNodes[v].index) {
|
if(tarjan_node_list[v].lowlink == tarjan_node_list[v].index) {
|
||||||
NodeID vprime;
|
NodeID vprime;
|
||||||
do {
|
do {
|
||||||
// SimpleLogger().Write() << "identified component " << currentComponent << ": " << tarjanStack.top();
|
vprime = tarjan_stack.top(); tarjan_stack.pop();
|
||||||
vprime = tarjanStack.top(); tarjanStack.pop();
|
tarjan_node_list[vprime].onStack = false;
|
||||||
tarjanNodes[vprime].onStack = false;
|
components_index[vprime] = component_index;
|
||||||
componentsIndex[vprime] = currentComponent;
|
++size_of_current_component;
|
||||||
++sizeOfCurrentComponent;
|
|
||||||
} while( v != vprime);
|
} while( v != vprime);
|
||||||
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
|
|
||||||
if(sizeOfCurrentComponent > 1000)
|
component_size_vector.push_back(size_of_current_component);
|
||||||
SimpleLogger().Write() << "large component [" << currentComponent << "]=" << sizeOfCurrentComponent;
|
|
||||||
++currentComponent;
|
if(size_of_current_component > 1000) {
|
||||||
sizeOfCurrentComponent = 0;
|
SimpleLogger().Write() <<
|
||||||
|
"large component [" << component_index << "]=" <<
|
||||||
|
size_of_current_component;
|
||||||
|
}
|
||||||
|
|
||||||
|
++component_index;
|
||||||
|
size_of_current_component = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleLogger().Write() << "identified: " << vectorOfComponentSizes.size() << " many components, marking small components";
|
SimpleLogger().Write() <<
|
||||||
|
"identified: " << component_size_vector.size() <<
|
||||||
|
" many components, marking small components";
|
||||||
|
|
||||||
int singleCounter = 0;
|
unsigned size_one_counter = 0;
|
||||||
for(unsigned i = 0; i < vectorOfComponentSizes.size(); ++i){
|
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
|
||||||
if(1 == vectorOfComponentSizes[i])
|
if(1 == component_size_vector[i]) {
|
||||||
++singleCounter;
|
++size_one_counter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SimpleLogger().Write() << "identified " << singleCounter << " SCCs of size 1";
|
|
||||||
|
SimpleLogger().Write() <<
|
||||||
|
"identified " << size_one_counter << " SCCs of size 1";
|
||||||
|
|
||||||
uint64_t total_network_distance = 0;
|
uint64_t total_network_distance = 0;
|
||||||
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
|
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||||
for(TarjanDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
|
for(
|
||||||
|
TarjanDynamicGraph::NodeIterator u = 0, last_u_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
|
u < last_u_node;
|
||||||
|
++u
|
||||||
|
) {
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
for(TarjanDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
|
for(
|
||||||
if(_nodeBasedGraph->GetEdgeData(e1).reversedEdge) {
|
TarjanDynamicGraph::EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge = m_node_based_graph->EndEdges(u);
|
||||||
|
e1 < last_edge;
|
||||||
|
++e1
|
||||||
|
) {
|
||||||
|
if(!m_node_based_graph->GetEdgeData(e1).reversedEdge) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TarjanDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
|
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||||
|
|
||||||
total_network_distance += 100*ApproximateDistance(
|
total_network_distance += 100*ApproximateDistance(
|
||||||
inputNodeInfoList[u].lat,
|
m_coordinate_list[u].lat,
|
||||||
inputNodeInfoList[u].lon,
|
m_coordinate_list[u].lon,
|
||||||
inputNodeInfoList[v].lat,
|
m_coordinate_list[v].lat,
|
||||||
inputNodeInfoList[v].lon
|
m_coordinate_list[v].lon
|
||||||
);
|
);
|
||||||
|
|
||||||
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
|
if( SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type ) {
|
||||||
assert(e1 != UINT_MAX);
|
BOOST_ASSERT(e1 != UINT_MAX);
|
||||||
assert(u != UINT_MAX);
|
BOOST_ASSERT(u != UINT_MAX);
|
||||||
assert(v != UINT_MAX);
|
BOOST_ASSERT(v != UINT_MAX);
|
||||||
|
|
||||||
|
const unsigned size_of_containing_component =
|
||||||
|
std::min(
|
||||||
|
component_size_vector[components_index[u]],
|
||||||
|
component_size_vector[components_index[v]]
|
||||||
|
);
|
||||||
|
|
||||||
//edges that end on bollard nodes may actually be in two distinct components
|
//edges that end on bollard nodes may actually be in two distinct components
|
||||||
if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) {
|
if(size_of_containing_component < 10) {
|
||||||
|
|
||||||
//INFO("(" << inputNodeInfoList[u].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[u].lon/COORDINATE_PRECISION << ") -> (" << inputNodeInfoList[v].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[v].lon/COORDINATE_PRECISION << ")");
|
|
||||||
OGRLineString lineString;
|
OGRLineString lineString;
|
||||||
lineString.addPoint(inputNodeInfoList[u].lon/COORDINATE_PRECISION, inputNodeInfoList[u].lat/COORDINATE_PRECISION);
|
lineString.addPoint(
|
||||||
lineString.addPoint(inputNodeInfoList[v].lon/COORDINATE_PRECISION, inputNodeInfoList[v].lat/COORDINATE_PRECISION);
|
m_coordinate_list[u].lon/COORDINATE_PRECISION,
|
||||||
OGRFeature *poFeature;
|
m_coordinate_list[u].lat/COORDINATE_PRECISION
|
||||||
poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
|
);
|
||||||
|
lineString.addPoint(
|
||||||
|
m_coordinate_list[v].lon/COORDINATE_PRECISION,
|
||||||
|
m_coordinate_list[v].lat/COORDINATE_PRECISION
|
||||||
|
);
|
||||||
|
|
||||||
|
OGRFeature * poFeature = OGRFeature::CreateFeature(
|
||||||
|
poLayer->GetLayerDefn()
|
||||||
|
);
|
||||||
|
|
||||||
poFeature->SetGeometry( &lineString );
|
poFeature->SetGeometry( &lineString );
|
||||||
if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) {
|
if( OGRERR_NONE != poLayer->CreateFeature(poFeature) ) {
|
||||||
throw OSRMException(
|
throw OSRMException(
|
||||||
"Failed to create feature in shapefile."
|
"Failed to create feature in shapefile."
|
||||||
);
|
);
|
||||||
@ -377,39 +427,66 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
OGRDataSource::DestroyDataSource( poDS );
|
OGRDataSource::DestroyDataSource( poDS );
|
||||||
std::vector<NodeID>().swap(vectorOfComponentSizes);
|
std::vector<NodeID>().swap(component_size_vector);
|
||||||
std::vector<NodeID>().swap(componentsIndex);
|
BOOST_ASSERT_MSG(
|
||||||
SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance/100/1000. << " km";
|
0 == component_size_vector.size() &&
|
||||||
|
0 == component_size_vector.capacity(),
|
||||||
|
"component_size_vector not properly deallocated"
|
||||||
|
);
|
||||||
|
|
||||||
|
std::vector<NodeID>().swap(components_index);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == components_index.size() && 0 == components_index.capacity(),
|
||||||
|
"icomponents_index not properly deallocated"
|
||||||
|
);
|
||||||
|
|
||||||
|
SimpleLogger().Write()
|
||||||
|
<< "total network distance: " <<
|
||||||
|
(uint64_t)total_network_distance/100/1000. <<
|
||||||
|
" km";
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
||||||
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
|
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||||
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
|
||||||
if (restrIter != _restrictionMap.end()) {
|
if (restriction_iterator != m_restriction_map.end()) {
|
||||||
unsigned index = restrIter->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) {
|
BOOST_FOREACH(
|
||||||
if(restrictionTarget.second) {
|
const RestrictionSource & restriction_target,
|
||||||
return restrictionTarget.first;
|
m_restriction_bucket_list.at(index)
|
||||||
|
) {
|
||||||
|
if(restriction_target.second) {
|
||||||
|
return restriction_target.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const {
|
|
||||||
|
bool CheckIfTurnIsRestricted(
|
||||||
|
const NodeID u,
|
||||||
|
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.
|
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
||||||
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
|
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||||
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
|
||||||
if (restrIter != _restrictionMap.end()) {
|
if (restriction_iterator != m_restriction_map.end()) {
|
||||||
unsigned index = restrIter->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
|
BOOST_FOREACH(
|
||||||
if(w == restrictionTarget.first)
|
const restriction_target & restriction_target,
|
||||||
|
m_restriction_bucket_list.at(index)
|
||||||
|
) {
|
||||||
|
if(w == restriction_target.first) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteFileIfExists(const std::string file_name) const {
|
void DeleteFileIfExists(const std::string & file_name) const {
|
||||||
if (boost::filesystem::exists(file_name) ) {
|
if (boost::filesystem::exists(file_name) ) {
|
||||||
boost::filesystem::remove(file_name);
|
boost::filesystem::remove(file_name);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user