bool ContractionHierarchiesClient::unpackEdge( const NodeIterator source, const NodeIterator target, bool forward, QVector< Node >* pathNodes, QVector< Edge >* pathEdges ) {
	EdgeIterator shortestEdge;

	unsigned distance = std::numeric_limits< unsigned >::max();
	for ( EdgeIterator edge = m_graph.edges( source ); edge.hasEdgesLeft(); ) {
		m_graph.unpackNextEdge( &edge );
		if ( edge.target() != target )
			continue;
		if ( forward && !edge.forward() )
			continue;
		if ( !forward && !edge.backward() )
			continue;
		if ( edge.distance() > distance )
			continue;
		distance = edge.distance();
		shortestEdge = edge;
	}

	if ( shortestEdge.unpacked() ) {
		m_graph.path( shortestEdge, pathNodes, pathEdges, forward );
		return true;
	}

	if ( !shortestEdge.shortcut() ) {
		pathEdges->push_back( shortestEdge.description() );
		if ( forward )
			pathNodes->push_back( m_graph.node( target ).coordinate );
		else
			pathNodes->push_back( m_graph.node( source ).coordinate );
		return true;
	}

	const NodeIterator middle = shortestEdge.middle();

	if ( forward ) {
		unpackEdge( middle, source, false, pathNodes, pathEdges );
		unpackEdge( middle, target, true, pathNodes, pathEdges );
		return true;
	} else {
		unpackEdge( middle, target, false, pathNodes, pathEdges );
		unpackEdge( middle, source, true, pathNodes, pathEdges );
		return true;
	}
}
void ContractionHierarchiesClient::computeStep( Heap* heapForward, Heap* heapBackward, const EdgeAllowed& edgeAllowed, const StallEdgeAllowed& stallEdgeAllowed, NodeIterator* middle, int* targetDistance ) {

	const NodeIterator node = heapForward->DeleteMin();
	const int distance = heapForward->GetKey( node );

	if ( heapForward->GetData( node ).stalled )
		return;

	if ( heapBackward->WasInserted( node ) && !heapBackward->GetData( node ).stalled ) {
		const int newDistance = heapBackward->GetKey( node ) + distance;
		if ( newDistance < *targetDistance ) {
			*middle = node;
			*targetDistance = newDistance;
		}
	}

	if ( distance > *targetDistance ) {
		heapForward->DeleteAll();
		return;
	}
	for ( EdgeIterator edge = m_graph.edges( node ); edge.hasEdgesLeft(); ) {
		m_graph.unpackNextEdge( &edge );
		const NodeIterator to = edge.target();
		const int edgeWeight = edge.distance();
		assert( edgeWeight > 0 );
		const int toDistance = distance + edgeWeight;

		if ( stallEdgeAllowed( edge.forward(), edge.backward() ) && heapForward->WasInserted( to ) ) {
			const int shorterDistance = heapForward->GetKey( to ) + edgeWeight;
			if ( shorterDistance < distance ) {
				//perform a bfs starting at node
				//only insert nodes when a sub-optimal path can be proven
				//insert node into the stall queue
				heapForward->GetKey( node ) = shorterDistance;
				heapForward->GetData( node ).stalled = true;
				m_stallQueue.push( node );

				while ( !m_stallQueue.empty() ) {
					//get node from the queue
					const NodeIterator stallNode = m_stallQueue.front();
					m_stallQueue.pop();
					const int stallDistance = heapForward->GetKey( stallNode );

					//iterate over outgoing edges
					for ( EdgeIterator stallEdge = m_graph.edges( stallNode ); stallEdge.hasEdgesLeft(); ) {
						m_graph.unpackNextEdge( &stallEdge );
						//is edge outgoing/reached/stalled?
						if ( !edgeAllowed( stallEdge.forward(), stallEdge.backward() ) )
							continue;
						const NodeIterator stallTo = stallEdge.target();
						if ( !heapForward->WasInserted( stallTo ) )
							continue;
						if ( heapForward->GetData( stallTo ).stalled == true )
							continue;

						const int stallToDistance = stallDistance + stallEdge.distance();
						//sub-optimal path found -> insert stallTo
						if ( stallToDistance < heapForward->GetKey( stallTo ) ) {
							if ( heapForward->WasRemoved( stallTo ) )
								heapForward->GetKey( stallTo ) = stallToDistance;
							else
								heapForward->DecreaseKey( stallTo, stallToDistance );

							m_stallQueue.push( stallTo );
							heapForward->GetData( stallTo ).stalled = true;
						}
					}
				}
				break;
			}
		}

		if ( edgeAllowed( edge.forward(), edge.backward() ) ) {
			//New Node discovered -> Add to Heap + Node Info Storage
			if ( !heapForward->WasInserted( to ) )
				heapForward->Insert( to, toDistance, node );

			//Found a shorter Path -> Update distance
			else if ( toDistance <= heapForward->GetKey( to ) ) {
				heapForward->DecreaseKey( to, toDistance );
				//new parent + unstall
				heapForward->GetData( to ).parent = node;
				heapForward->GetData( to ).stalled = false;
			}
		}
	}
}