2011-10-10 11:52:47 -04:00
/*
open source routing machine
Copyright ( C ) Dennis Luxen , others 2010
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
or see http : //www.gnu.org/licenses/agpl.txt.
*/
2011-11-09 10:12:05 -05:00
# include <algorithm>
2012-07-13 11:01:21 -04:00
# include <queue>
2011-11-09 10:12:05 -05:00
# include <boost/foreach.hpp>
2012-02-28 10:25:01 -05:00
# include <boost/lexical_cast.hpp>
# include <boost/property_tree/ptree.hpp>
# include <boost/property_tree/ini_parser.hpp>
2011-11-09 10:12:05 -05:00
2012-08-27 11:40:59 -04:00
# include "../Util/OpenMPWrapper.h"
2012-04-20 12:34:49 -04:00
# include "../DataStructures/Percent.h"
2011-10-10 11:52:47 -04:00
# include "EdgeBasedGraphFactory.h"
template < >
2012-08-13 10:47:24 -04:00
EdgeBasedGraphFactory : : EdgeBasedGraphFactory ( int nodes , std : : vector < NodeBasedEdge > & inputEdges , std : : vector < NodeID > & bn , std : : vector < NodeID > & tl , std : : vector < _Restriction > & irs , std : : vector < NodeInfo > & nI , boost : : property_tree : : ptree speedProfile , std : : string & srtm ) : inputNodeInfoList ( nI ) , numberOfTurnRestrictions ( irs . size ( ) ) , trafficSignalPenalty ( 0 ) , uturnPenalty ( 0 ) , takeMinimumOfSpeeds ( false ) {
2012-02-29 14:02:04 -05:00
BOOST_FOREACH ( _Restriction & restriction , irs ) {
std : : pair < NodeID , NodeID > restrictionSource = std : : make_pair ( restriction . fromNode , restriction . viaNode ) ;
unsigned index ;
RestrictionMap : : iterator restrIter = _restrictionMap . find ( restrictionSource ) ;
if ( restrIter = = _restrictionMap . end ( ) ) {
index = _restrictionBucketVector . size ( ) ;
_restrictionBucketVector . resize ( index + 1 ) ;
_restrictionMap [ restrictionSource ] = index ;
} else {
index = restrIter - > second ;
//Map already contains an is_only_*-restriction
if ( _restrictionBucketVector . at ( index ) . begin ( ) - > second )
continue ;
else if ( restriction . flags . isOnly ) {
//We are going to insert an is_only_*-restriction. There can be only one.
_restrictionBucketVector . at ( index ) . clear ( ) ;
}
}
_restrictionBucketVector . at ( index ) . push_back ( std : : make_pair ( restriction . toNode , restriction . flags . isOnly ) ) ;
}
2011-11-09 10:12:05 -05:00
2012-04-25 12:32:59 -04:00
std : : string usedSpeedProfile ( speedProfile . get_child ( " " ) . begin ( ) - > first ) ;
2012-02-28 10:25:01 -05:00
BOOST_FOREACH ( boost : : property_tree : : ptree : : value_type & v , speedProfile . get_child ( usedSpeedProfile ) ) {
if ( " trafficSignalPenalty " = = v . first ) {
std : : string value = v . second . get < std : : string > ( " " ) ;
try {
trafficSignalPenalty = 10 * boost : : lexical_cast < int > ( v . second . get < std : : string > ( " " ) ) ;
} catch ( boost : : bad_lexical_cast & ) {
trafficSignalPenalty = 0 ;
}
}
2012-03-20 07:35:52 -04:00
if ( " uturnPenalty " = = v . first ) {
std : : string value = v . second . get < std : : string > ( " " ) ;
try {
uturnPenalty = 10 * boost : : lexical_cast < int > ( v . second . get < std : : string > ( " " ) ) ;
} catch ( boost : : bad_lexical_cast & ) {
uturnPenalty = 0 ;
}
}
if ( " takeMinimumOfSpeeds " = = v . first ) {
std : : string value = v . second . get < std : : string > ( " " ) ;
takeMinimumOfSpeeds = ( v . second . get < std : : string > ( " " ) = = " yes " ) ;
}
2012-02-28 10:25:01 -05:00
}
2012-07-13 11:01:21 -04:00
// INFO("traffic signal penalty: " << trafficSignalPenalty << ", U-Turn penalty: " << uturnPenalty << ", takeMinimumOfSpeeds=" << (takeMinimumOfSpeeds ? "yes" : "no"));
2012-03-05 03:36:20 -05:00
2012-04-04 05:11:54 -04:00
BOOST_FOREACH ( NodeID id , bn ) {
_barrierNodes [ id ] = true ;
}
BOOST_FOREACH ( NodeID id , tl ) {
_trafficLights [ id ] = true ;
}
2011-11-09 10:12:05 -05:00
2012-05-23 15:18:38 -04:00
DeallocatingVector < _NodeBasedEdge > edges ;
2012-07-13 11:01:21 -04:00
// edges.reserve( 2 * inputEdges.size() );
2012-03-08 05:35:40 -05:00
for ( std : : vector < NodeBasedEdge > : : const_iterator i = inputEdges . begin ( ) ; i ! = inputEdges . end ( ) ; + + i ) {
2011-10-10 11:52:47 -04:00
2012-03-08 05:35:40 -05:00
_NodeBasedEdge edge ;
if ( ! i - > isForward ( ) ) {
edge . source = i - > target ( ) ;
edge . target = i - > source ( ) ;
edge . data . backward = i - > isForward ( ) ;
edge . data . forward = i - > isBackward ( ) ;
2012-07-13 11:01:21 -04:00
} else {
2012-03-08 05:35:40 -05:00
edge . source = i - > source ( ) ;
edge . target = i - > target ( ) ;
edge . data . forward = i - > isForward ( ) ;
edge . data . backward = i - > isBackward ( ) ;
}
2011-11-09 10:12:05 -05:00
if ( edge . source = = edge . target )
continue ;
2011-10-10 11:52:47 -04:00
edge . data . distance = ( std : : max ) ( ( int ) i - > weight ( ) , 1 ) ;
assert ( edge . data . distance > 0 ) ;
edge . data . shortcut = false ;
2011-11-22 10:47:15 -05:00
edge . data . roundabout = i - > isRoundabout ( ) ;
2011-12-16 08:05:30 -05:00
edge . data . ignoreInGrid = i - > ignoreInGrid ( ) ;
2011-11-25 06:02:52 -05:00
edge . data . nameID = i - > name ( ) ;
2011-10-10 11:52:47 -04:00
edge . data . type = i - > type ( ) ;
2012-03-22 05:25:04 -04:00
edge . data . isAccessRestricted = i - > isAccessRestricted ( ) ;
2011-11-14 07:12:56 -05:00
edge . data . edgeBasedNodeID = edges . size ( ) ;
2011-10-10 11:52:47 -04:00
edges . push_back ( edge ) ;
2011-11-09 10:12:05 -05:00
if ( edge . data . backward ) {
2011-12-05 08:45:45 -05:00
std : : swap ( edge . source , edge . target ) ;
2011-11-09 10:12:05 -05:00
edge . data . forward = i - > isBackward ( ) ;
edge . data . backward = i - > isForward ( ) ;
2011-11-14 07:12:56 -05:00
edge . data . edgeBasedNodeID = edges . size ( ) ;
2011-11-09 10:12:05 -05:00
edges . push_back ( edge ) ;
}
2011-10-10 11:52:47 -04:00
}
2012-04-25 12:56:42 -04:00
std : : vector < NodeBasedEdge > ( ) . swap ( inputEdges ) ;
2012-05-23 15:18:38 -04:00
//std::vector<_NodeBasedEdge>(edges).swap(edges);
2012-03-22 05:25:04 -04:00
std : : sort ( edges . begin ( ) , edges . end ( ) ) ;
2011-11-09 10:12:05 -05:00
_nodeBasedGraph . reset ( new _NodeBasedDynamicGraph ( nodes , edges ) ) ;
}
2012-05-23 15:18:38 -04:00
void EdgeBasedGraphFactory : : GetEdgeBasedEdges ( DeallocatingVector < EdgeBasedEdge > & outputEdgeList ) {
2011-11-25 06:02:52 -05:00
GUARANTEE ( 0 = = outputEdgeList . size ( ) , " Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty " ) ;
2011-11-09 10:12:05 -05:00
GUARANTEE ( 0 ! = edgeBasedEdges . size ( ) , " No edges in edge based graph " ) ;
2011-11-25 06:02:52 -05:00
edgeBasedEdges . swap ( outputEdgeList ) ;
2011-11-09 10:12:05 -05:00
}
2012-08-22 11:36:30 -04:00
void EdgeBasedGraphFactory : : GetEdgeBasedNodes ( DeallocatingVector < EdgeBasedNode > & nodes ) {
2011-12-13 04:12:41 -05:00
BOOST_FOREACH ( EdgeBasedNode & node , edgeBasedNodes ) {
2012-03-01 08:36:10 -05:00
assert ( node . lat1 ! = INT_MAX ) ; assert ( node . lon1 ! = INT_MAX ) ;
assert ( node . lat2 ! = INT_MAX ) ; assert ( node . lon2 ! = INT_MAX ) ;
2011-12-13 04:12:41 -05:00
}
2012-03-01 08:36:10 -05:00
nodes . swap ( edgeBasedNodes ) ;
2011-11-09 10:12:05 -05:00
}
2012-04-25 04:51:16 -04:00
void EdgeBasedGraphFactory : : GetOriginalEdgeData ( std : : vector < OriginalEdgeData > & oed ) {
oed . swap ( originalEdgeData ) ;
}
2012-02-29 14:02:04 -05:00
NodeID EdgeBasedGraphFactory : : CheckForEmanatingIsOnlyTurn ( const NodeID u , const NodeID v ) const {
std : : pair < NodeID , NodeID > restrictionSource = std : : make_pair ( u , v ) ;
RestrictionMap : : const_iterator restrIter = _restrictionMap . find ( restrictionSource ) ;
if ( restrIter ! = _restrictionMap . end ( ) ) {
unsigned index = restrIter - > second ;
2012-03-01 08:36:10 -05:00
BOOST_FOREACH ( RestrictionSource restrictionTarget , _restrictionBucketVector . at ( index ) ) {
2012-02-29 14:02:04 -05:00
if ( restrictionTarget . second ) {
return restrictionTarget . first ;
}
}
}
return UINT_MAX ;
}
bool EdgeBasedGraphFactory : : 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.
std : : pair < NodeID , NodeID > restrictionSource = std : : make_pair ( u , v ) ;
RestrictionMap : : const_iterator restrIter = _restrictionMap . find ( restrictionSource ) ;
if ( restrIter ! = _restrictionMap . end ( ) ) {
unsigned index = restrIter - > second ;
BOOST_FOREACH ( RestrictionTarget restrictionTarget , _restrictionBucketVector . at ( index ) ) {
2012-03-01 08:36:10 -05:00
if ( w = = restrictionTarget . first )
2012-02-29 14:02:04 -05:00
return true ;
}
}
return false ;
}
2012-03-01 13:41:06 -05:00
void EdgeBasedGraphFactory : : InsertEdgeBasedNode (
_NodeBasedDynamicGraph : : EdgeIterator e1 ,
_NodeBasedDynamicGraph : : NodeIterator u ,
2012-07-13 11:01:21 -04:00
_NodeBasedDynamicGraph : : NodeIterator v ,
bool belongsToTinyComponent ) {
2012-03-05 08:34:38 -05:00
_NodeBasedDynamicGraph : : EdgeData & data = _nodeBasedGraph - > GetEdgeData ( e1 ) ;
2012-03-01 13:41:06 -05:00
EdgeBasedNode currentNode ;
2012-03-05 08:34:38 -05:00
currentNode . nameID = data . nameID ;
2012-03-01 13:41:06 -05:00
currentNode . lat1 = inputNodeInfoList [ u ] . lat ;
currentNode . lon1 = inputNodeInfoList [ u ] . lon ;
currentNode . lat2 = inputNodeInfoList [ v ] . lat ;
currentNode . lon2 = inputNodeInfoList [ v ] . lon ;
2012-07-13 11:01:21 -04:00
currentNode . belongsToTinyComponent = belongsToTinyComponent ;
2012-03-05 08:34:38 -05:00
currentNode . id = data . edgeBasedNodeID ;
currentNode . ignoreInGrid = data . ignoreInGrid ;
currentNode . weight = data . distance ;
2012-03-01 13:41:06 -05:00
edgeBasedNodes . push_back ( currentNode ) ;
}
2012-04-27 10:50:34 -04:00
void EdgeBasedGraphFactory : : Run ( const char * originalEdgeDataFilename ) {
2011-11-09 10:12:05 -05:00
Percent p ( _nodeBasedGraph - > GetNumberOfNodes ( ) ) ;
2011-12-30 07:30:17 -05:00
int numberOfSkippedTurns ( 0 ) ;
2011-11-09 10:12:05 -05:00
int nodeBasedEdgeCounter ( 0 ) ;
2012-04-27 10:50:34 -04:00
unsigned numberOfOriginalEdges ( 0 ) ;
std : : ofstream originalEdgeDataOutFile ( originalEdgeDataFilename , std : : ios : : binary ) ;
originalEdgeDataOutFile . write ( ( char * ) & numberOfOriginalEdges , sizeof ( unsigned ) ) ;
2012-04-20 12:34:49 -04:00
2012-07-13 11:01:21 -04:00
INFO ( " Identifying small components " ) ;
//Run a BFS on the undirected graph and identify small components
std : : queue < std : : pair < NodeID , NodeID > > bfsQueue ;
std : : vector < unsigned > componentsIndex ( _nodeBasedGraph - > GetNumberOfNodes ( ) , UINT_MAX ) ;
std : : vector < NodeID > vectorOfComponentSizes ;
unsigned currentComponent = 0 , sizeOfCurrentComponent = 0 , settledNodes = 0 ;
//put unexplorered node with parent pointer into queue
for ( NodeID node = 0 , endNodes = _nodeBasedGraph - > GetNumberOfNodes ( ) ; node < endNodes ; + + node ) {
if ( UINT_MAX = = componentsIndex [ node ] ) {
bfsQueue . push ( std : : make_pair ( node , node ) ) ;
//mark node as read
componentsIndex [ node ] = currentComponent ;
p . printIncrement ( ) ;
while ( ! bfsQueue . empty ( ) ) {
//fetch element from BFS queue
std : : pair < NodeID , NodeID > currentQueueItem = bfsQueue . front ( ) ;
bfsQueue . pop ( ) ;
// INFO("sizeof queue: " << bfsQueue.size() << ", sizeOfCurrentComponents: " << sizeOfCurrentComponent << ", settled nodes: " << settledNodes++ << ", max: " << endNodes);
const NodeID v = currentQueueItem . first ; //current node
const NodeID u = currentQueueItem . second ; //parent
//increment size counter of current component
+ + sizeOfCurrentComponent ;
const bool isBollardNode = ( _barrierNodes . find ( v ) ! = _barrierNodes . end ( ) ) ;
if ( ! isBollardNode ) {
const NodeID onlyToNode = CheckForEmanatingIsOnlyTurn ( u , v ) ;
//relaxieren edge outgoing edge like below where edge-expanded graph
for ( _NodeBasedDynamicGraph : : EdgeIterator e2 = _nodeBasedGraph - > BeginEdges ( v ) ; e2 < _nodeBasedGraph - > EndEdges ( v ) ; + + e2 ) {
_NodeBasedDynamicGraph : : NodeIterator w = _nodeBasedGraph - > GetTarget ( e2 ) ;
if ( onlyToNode ! = UINT_MAX & & w ! = onlyToNode ) { //We are at an only_-restriction but not at the right turn.
continue ;
}
if ( u ! = w ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
if ( ! CheckIfTurnIsRestricted ( u , v , w ) ) { //only add an edge if turn is not prohibited
//insert next (node, parent) only if w has not yet been explored
if ( UINT_MAX = = componentsIndex [ w ] ) {
//mark node as read
componentsIndex [ w ] = currentComponent ;
bfsQueue . push ( std : : make_pair ( w , v ) ) ;
p . printIncrement ( ) ;
}
}
}
}
}
}
//push size into vector
vectorOfComponentSizes . push_back ( sizeOfCurrentComponent ) ;
//reset counters;
sizeOfCurrentComponent = 0 ;
+ + currentComponent ;
}
}
INFO ( " identified: " < < vectorOfComponentSizes . size ( ) < < " many components " ) ;
p . reinit ( _nodeBasedGraph - > GetNumberOfNodes ( ) ) ;
2012-04-20 12:34:49 -04:00
//loop over all edges and generate new set of nodes.
for ( _NodeBasedDynamicGraph : : NodeIterator u = 0 ; u < _nodeBasedGraph - > GetNumberOfNodes ( ) ; + + u ) {
for ( _NodeBasedDynamicGraph : : EdgeIterator e1 = _nodeBasedGraph - > BeginEdges ( u ) ; e1 < _nodeBasedGraph - > EndEdges ( u ) ; + + e1 ) {
_NodeBasedDynamicGraph : : NodeIterator v = _nodeBasedGraph - > GetTarget ( e1 ) ;
2012-04-25 12:56:42 -04:00
2012-03-01 08:36:10 -05:00
if ( _nodeBasedGraph - > GetEdgeData ( e1 ) . type ! = SHRT_MAX ) {
2012-03-05 08:34:38 -05:00
assert ( e1 ! = UINT_MAX ) ;
assert ( u ! = UINT_MAX ) ;
assert ( v ! = UINT_MAX ) ;
2012-07-13 11:01:21 -04:00
//edges that end on bollard nodes may actually be in two distinct components
InsertEdgeBasedNode ( e1 , u , v , ( std : : min ( vectorOfComponentSizes [ componentsIndex [ u ] ] , vectorOfComponentSizes [ componentsIndex [ v ] ] ) < 1000 ) ) ;
2011-12-05 08:45:45 -05:00
}
2012-03-01 08:36:10 -05:00
}
}
2012-01-01 10:04:59 -05:00
2012-07-16 07:20:56 -04:00
std : : vector < NodeID > ( ) . swap ( vectorOfComponentSizes ) ;
std : : vector < NodeID > ( ) . swap ( componentsIndex ) ;
2012-03-01 08:36:10 -05:00
//Loop over all turns and generate new set of edges.
//Three nested loop look super-linear, but we are dealing with a linear number of turns only.
for ( _NodeBasedDynamicGraph : : NodeIterator u = 0 ; u < _nodeBasedGraph - > GetNumberOfNodes ( ) ; + + u ) {
for ( _NodeBasedDynamicGraph : : EdgeIterator e1 = _nodeBasedGraph - > BeginEdges ( u ) ; e1 < _nodeBasedGraph - > EndEdges ( u ) ; + + e1 ) {
2012-03-07 08:08:46 -05:00
+ + nodeBasedEdgeCounter ;
2012-03-01 08:36:10 -05:00
_NodeBasedDynamicGraph : : NodeIterator v = _nodeBasedGraph - > GetTarget ( e1 ) ;
//EdgeWeight heightPenalty = ComputeHeightPenalty(u, v);
NodeID onlyToNode = CheckForEmanatingIsOnlyTurn ( u , v ) ;
2011-11-09 10:12:05 -05:00
for ( _NodeBasedDynamicGraph : : EdgeIterator e2 = _nodeBasedGraph - > BeginEdges ( v ) ; e2 < _nodeBasedGraph - > EndEdges ( v ) ; + + e2 ) {
_NodeBasedDynamicGraph : : NodeIterator w = _nodeBasedGraph - > GetTarget ( e2 ) ;
2012-02-07 13:40:25 -05:00
2012-03-01 08:36:10 -05:00
if ( onlyToNode ! = UINT_MAX & & w ! = onlyToNode ) { //We are at an only_-restriction but not at the right turn.
2012-02-29 14:02:04 -05:00
+ + numberOfSkippedTurns ;
2011-12-05 08:45:45 -05:00
continue ;
}
2012-03-01 08:36:10 -05:00
bool isBollardNode = ( _barrierNodes . find ( v ) ! = _barrierNodes . end ( ) ) ;
2012-03-01 13:41:06 -05:00
if ( ( ! isBollardNode & & ( u ! = w | | 1 = = _nodeBasedGraph - > GetOutDegree ( v ) ) ) | | ( ( u = = w ) & & isBollardNode ) ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
2012-02-29 14:02:04 -05:00
if ( ! CheckIfTurnIsRestricted ( u , v , w ) | | ( onlyToNode ! = UINT_MAX & & w = = onlyToNode ) ) { //only add an edge if turn is not prohibited
2012-03-01 08:36:10 -05:00
const _NodeBasedDynamicGraph : : EdgeData edgeData1 = _nodeBasedGraph - > GetEdgeData ( e1 ) ;
const _NodeBasedDynamicGraph : : EdgeData edgeData2 = _nodeBasedGraph - > GetEdgeData ( e2 ) ;
assert ( edgeData1 . edgeBasedNodeID < _nodeBasedGraph - > GetNumberOfEdges ( ) ) ;
assert ( edgeData2 . edgeBasedNodeID < _nodeBasedGraph - > GetNumberOfEdges ( ) ) ;
2012-07-13 11:01:21 -04:00
if ( ! edgeData1 . forward | | ! edgeData2 . forward )
continue ;
2012-03-01 08:36:10 -05:00
unsigned distance = edgeData1 . distance ;
2012-02-28 10:25:01 -05:00
if ( _trafficLights . find ( v ) ! = _trafficLights . end ( ) ) {
distance + = trafficSignalPenalty ;
}
2012-03-01 08:36:10 -05:00
short turnInstruction = AnalyzeTurn ( u , v , w ) ;
2012-03-20 07:35:52 -04:00
if ( turnInstruction = = TurnInstructions . UTurn )
distance + = uturnPenalty ;
2012-07-25 12:32:32 -04:00
// if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) {
// distance += TurnInstructions.AccessRestrictionPenalty;
// turnInstruction |= TurnInstructions.AccessRestrictionFlag;
// }
2012-03-22 05:25:04 -04:00
2012-07-13 11:01:21 -04:00
2012-03-20 07:35:52 -04:00
//distance += heightPenalty;
//distance += ComputeTurnPenalty(u, v, w);
2012-03-05 08:34:38 -05:00
assert ( edgeData1 . edgeBasedNodeID ! = edgeData2 . edgeBasedNodeID ) ;
2012-04-26 03:59:39 -04:00
if ( originalEdgeData . size ( ) = = originalEdgeData . capacity ( ) - 3 ) {
2012-05-15 05:40:41 -04:00
originalEdgeData . reserve ( originalEdgeData . size ( ) * 1.2 ) ;
2012-04-26 03:59:39 -04:00
}
2012-04-25 04:51:16 -04:00
OriginalEdgeData oed ( v , edgeData2 . nameID , turnInstruction ) ;
EdgeBasedEdge newEdge ( edgeData1 . edgeBasedNodeID , edgeData2 . edgeBasedNodeID , edgeBasedEdges . size ( ) , distance , true , false ) ;
originalEdgeData . push_back ( oed ) ;
2012-04-27 10:50:34 -04:00
if ( originalEdgeData . size ( ) > 100000 ) {
originalEdgeDataOutFile . write ( ( char * ) & ( originalEdgeData [ 0 ] ) , originalEdgeData . size ( ) * sizeof ( OriginalEdgeData ) ) ;
originalEdgeData . clear ( ) ;
}
+ + numberOfOriginalEdges ;
+ + nodeBasedEdgeCounter ;
2011-11-09 10:12:05 -05:00
edgeBasedEdges . push_back ( newEdge ) ;
} else {
2011-12-30 07:30:17 -05:00
+ + numberOfSkippedTurns ;
2011-11-09 10:12:05 -05:00
}
}
2011-10-10 11:52:47 -04:00
}
}
2011-11-09 10:12:05 -05:00
p . printIncrement ( ) ;
2011-10-10 11:52:47 -04:00
}
2012-04-27 10:50:34 -04:00
numberOfOriginalEdges + = originalEdgeData . size ( ) ;
originalEdgeDataOutFile . write ( ( char * ) & ( originalEdgeData [ 0 ] ) , originalEdgeData . size ( ) * sizeof ( OriginalEdgeData ) ) ;
originalEdgeDataOutFile . seekp ( std : : ios : : beg ) ;
originalEdgeDataOutFile . write ( ( char * ) & numberOfOriginalEdges , sizeof ( unsigned ) ) ;
originalEdgeDataOutFile . close ( ) ;
2012-08-22 12:44:14 -04:00
// INFO("Sorting edge-based Nodes");
// std::sort(edgeBasedNodes.begin(), edgeBasedNodes.end());
2012-08-22 11:36:30 -04:00
// INFO("Removing duplicate nodes (if any)");
// edgeBasedNodes.erase( std::unique(edgeBasedNodes.begin(), edgeBasedNodes.end()), edgeBasedNodes.end() );
2012-08-14 07:44:34 -04:00
// INFO("Applying vector self-swap trick to free up memory");
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
2012-08-22 11:36:30 -04:00
// std::vector<EdgeBasedNode>(edgeBasedNodes).swap(edgeBasedNodes);
2012-08-14 07:44:34 -04:00
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
2011-11-14 07:12:56 -05:00
INFO ( " Node-based graph contains " < < nodeBasedEdgeCounter < < " edges " ) ;
2012-08-14 07:44:34 -04:00
// INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges, blowup is " << 2*((double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter));
2012-02-29 14:02:04 -05:00
INFO ( " Edge-based graph skipped " < < numberOfSkippedTurns < < " turns, defined by " < < numberOfTurnRestrictions < < " restrictions. " ) ;
2011-11-14 07:12:56 -05:00
INFO ( " Generated " < < edgeBasedNodes . size ( ) < < " edge based nodes " ) ;
2011-11-09 10:12:05 -05:00
}
2011-11-17 12:04:49 -05:00
short EdgeBasedGraphFactory : : AnalyzeTurn ( const NodeID u , const NodeID v , const NodeID w ) const {
2012-02-29 14:02:04 -05:00
if ( u = = w ) {
return TurnInstructions . UTurn ;
}
2012-01-01 10:04:59 -05:00
2011-11-17 12:04:49 -05:00
_NodeBasedDynamicGraph : : EdgeIterator edge1 = _nodeBasedGraph - > FindEdge ( u , v ) ;
_NodeBasedDynamicGraph : : EdgeIterator edge2 = _nodeBasedGraph - > FindEdge ( v , w ) ;
2011-11-25 06:02:52 -05:00
_NodeBasedDynamicGraph : : EdgeData & data1 = _nodeBasedGraph - > GetEdgeData ( edge1 ) ;
_NodeBasedDynamicGraph : : EdgeData & data2 = _nodeBasedGraph - > GetEdgeData ( edge2 ) ;
2011-11-17 12:04:49 -05:00
2011-11-23 12:40:54 -05:00
//roundabouts need to be handled explicitely
if ( data1 . roundabout & & data2 . roundabout ) {
//Is a turn possible? If yes, we stay on the roundabout!
if ( 1 = = ( _nodeBasedGraph - > EndEdges ( v ) - _nodeBasedGraph - > BeginEdges ( v ) ) ) {
//No turn possible.
return TurnInstructions . NoTurn ;
} else {
return TurnInstructions . StayOnRoundAbout ;
}
}
//Does turn start or end on roundabout?
2011-11-22 10:47:15 -05:00
if ( data1 . roundabout | | data2 . roundabout ) {
//We are entering the roundabout
2011-11-23 12:40:54 -05:00
if ( ( ! data1 . roundabout ) & & data2 . roundabout )
2011-11-22 10:47:15 -05:00
return TurnInstructions . EnterRoundAbout ;
//We are leaving the roundabout
2012-03-08 05:35:40 -05:00
else if ( data1 . roundabout & & ( ! data2 . roundabout ) )
2011-11-22 10:47:15 -05:00
return TurnInstructions . LeaveRoundAbout ;
2011-11-17 12:04:49 -05:00
}
2011-11-22 10:47:15 -05:00
2011-11-23 12:40:54 -05:00
//If street names stay the same and if we are certain that it is not a roundabout, we skip it.
2012-02-08 12:31:37 -05:00
if ( ( data1 . nameID = = data2 . nameID ) & & ( 0 ! = data1 . nameID ) )
return TurnInstructions . NoTurn ;
2012-02-23 10:29:55 -05:00
if ( ( data1 . nameID = = data2 . nameID ) & & ( 0 = = data1 . nameID ) & & ( _nodeBasedGraph - > GetOutDegree ( v ) < = 2 ) )
2011-11-23 12:40:54 -05:00
return TurnInstructions . NoTurn ;
2012-02-08 12:31:37 -05:00
double angle = GetAngleBetweenTwoEdges ( inputNodeInfoList [ u ] , inputNodeInfoList [ v ] , inputNodeInfoList [ w ] ) ;
2011-11-22 10:47:15 -05:00
return TurnInstructions . GetTurnDirectionOfInstruction ( angle ) ;
2011-11-17 12:04:49 -05:00
}
2011-11-09 10:12:05 -05:00
unsigned EdgeBasedGraphFactory : : GetNumberOfNodes ( ) const {
2011-12-13 04:12:41 -05:00
return _nodeBasedGraph - > GetNumberOfEdges ( ) ;
2011-10-10 11:52:47 -04:00
}
2011-11-22 10:47:15 -05:00
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
template < class CoordinateT >
double EdgeBasedGraphFactory : : GetAngleBetweenTwoEdges ( const CoordinateT & A , const CoordinateT & C , const CoordinateT & B ) const {
const int v1x = A . lon - C . lon ;
const int v1y = A . lat - C . lat ;
const int v2x = B . lon - C . lon ;
const int v2y = B . lat - C . lat ;
double angle = ( atan2 ( ( double ) v2y , v2x ) - atan2 ( ( double ) v1y , v1x ) ) * 180 / M_PI ;
while ( angle < 0 )
angle + = 360 ;
return angle ;
}