2012-06-15 12:47:27 -04:00
|
|
|
/*
|
|
|
|
|
2013-10-14 07:42:28 -04:00
|
|
|
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.
|
|
|
|
|
|
|
|
*/
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
|
|
#ifndef BASICROUTINGINTERFACE_H_
|
|
|
|
#define BASICROUTINGINTERFACE_H_
|
|
|
|
|
2013-08-14 07:41:23 -04:00
|
|
|
#include "../DataStructures/RawRouteData.h"
|
2013-09-19 12:53:34 -04:00
|
|
|
#include "../DataStructures/SearchEngineData.h"
|
2014-02-11 05:42:24 -05:00
|
|
|
#include "../DataStructures/TurnInstructions.h"
|
2013-06-24 14:12:34 -04:00
|
|
|
#include "../Util/ContainerUtils.h"
|
2013-08-08 08:17:01 -04:00
|
|
|
#include "../Util/SimpleLogger.h"
|
2013-06-24 14:12:34 -04:00
|
|
|
|
2013-09-20 05:35:59 -04:00
|
|
|
#include <boost/assert.hpp>
|
2013-02-03 10:47:32 -05:00
|
|
|
#include <boost/noncopyable.hpp>
|
|
|
|
|
2013-06-24 14:12:34 -04:00
|
|
|
#include <stack>
|
2012-06-19 11:26:34 -04:00
|
|
|
|
2013-09-24 03:55:02 -04:00
|
|
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
|
|
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap;
|
|
|
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2;
|
|
|
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
|
|
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
|
|
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
|
|
|
|
2013-09-20 05:09:07 -04:00
|
|
|
template<class DataFacadeT>
|
2013-09-20 07:08:18 -04:00
|
|
|
class BasicRoutingInterface : boost::noncopyable {
|
2013-09-24 04:10:50 -04:00
|
|
|
private:
|
|
|
|
typedef typename DataFacadeT::EdgeData EdgeData;
|
2012-06-15 12:47:27 -04:00
|
|
|
protected:
|
2013-09-20 05:09:07 -04:00
|
|
|
DataFacadeT * facade;
|
2012-06-15 12:47:27 -04:00
|
|
|
public:
|
2014-04-16 10:21:16 -04:00
|
|
|
explicit BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
|
2012-06-15 12:47:27 -04:00
|
|
|
virtual ~BasicRoutingInterface(){ };
|
|
|
|
|
2013-09-19 12:53:34 -04:00
|
|
|
inline void RoutingStep(
|
2013-09-20 07:08:18 -04:00
|
|
|
SearchEngineData::QueryHeap & forward_heap,
|
|
|
|
SearchEngineData::QueryHeap & reverse_heap,
|
|
|
|
NodeID * middle_node_id,
|
|
|
|
int * upper_bound,
|
|
|
|
const bool forward_direction
|
2014-04-08 19:47:52 -04:00
|
|
|
) const
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
const NodeID node = forward_heap.DeleteMin();
|
|
|
|
const int distance = forward_heap.GetKey(node);
|
2014-04-08 19:47:52 -04:00
|
|
|
if (reverse_heap.WasInserted(node))
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
const int new_distance = reverse_heap.GetKey(node) + distance;
|
2014-04-08 19:47:52 -04:00
|
|
|
if(new_distance < *upper_bound )
|
|
|
|
{
|
2014-04-11 14:03:39 -04:00
|
|
|
if (new_distance >= 0)
|
2014-04-08 19:47:52 -04:00
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
*middle_node_id = node;
|
|
|
|
*upper_bound = new_distance;
|
2012-06-15 12:47:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-08 19:47:52 -04:00
|
|
|
if (distance > *upper_bound)
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
forward_heap.DeleteAll();
|
2012-06-15 12:47:27 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-03 10:47:32 -05:00
|
|
|
//Stalling
|
2014-04-25 10:00:39 -04:00
|
|
|
for (EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); ++edge)
|
|
|
|
{
|
2013-09-24 04:10:50 -04:00
|
|
|
const EdgeData & data = facade->GetEdgeData(edge);
|
2014-04-25 10:00:39 -04:00
|
|
|
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
|
|
|
if (reverse_flag)
|
|
|
|
{
|
2013-09-20 05:09:07 -04:00
|
|
|
const NodeID to = facade->GetTarget(edge);
|
2013-09-20 07:08:18 -04:00
|
|
|
const int edge_weight = data.distance;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
2014-04-25 10:00:39 -04:00
|
|
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
2012-06-15 12:47:27 -04:00
|
|
|
|
2014-04-25 10:00:39 -04:00
|
|
|
if (forward_heap.WasInserted(to))
|
|
|
|
{
|
|
|
|
if(forward_heap.GetKey( to ) + edge_weight < distance)
|
|
|
|
{
|
2012-06-15 12:47:27 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-22 10:15:38 -04:00
|
|
|
|
2014-04-25 10:00:39 -04:00
|
|
|
for (EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); edge < end_edge; ++edge)
|
|
|
|
{
|
2013-09-24 04:10:50 -04:00
|
|
|
const EdgeData & data = facade->GetEdgeData(edge);
|
2014-04-25 10:00:39 -04:00
|
|
|
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
|
|
|
if (forward_directionFlag)
|
|
|
|
{
|
2012-06-15 12:47:27 -04:00
|
|
|
|
2013-09-20 05:09:07 -04:00
|
|
|
const NodeID to = facade->GetTarget(edge);
|
2013-09-20 07:08:18 -04:00
|
|
|
const int edge_weight = data.distance;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
2013-09-20 07:08:18 -04:00
|
|
|
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
|
|
|
|
const int to_distance = distance + edge_weight;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
|
|
//New Node discovered -> Add to Heap + Node Info Storage
|
2013-09-20 07:08:18 -04:00
|
|
|
if ( !forward_heap.WasInserted( to ) ) {
|
|
|
|
forward_heap.Insert( to, to_distance, node );
|
2012-06-15 12:47:27 -04:00
|
|
|
}
|
|
|
|
//Found a shorter Path -> Update distance
|
2013-09-20 07:08:18 -04:00
|
|
|
else if ( to_distance < forward_heap.GetKey( to ) ) {
|
2014-04-25 09:48:10 -04:00
|
|
|
//new parent
|
2013-09-20 07:08:18 -04:00
|
|
|
forward_heap.GetData( to ).parent = node;
|
|
|
|
forward_heap.DecreaseKey( to, to_distance );
|
2012-06-15 12:47:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-25 10:00:39 -04:00
|
|
|
inline void UnpackPath(const std::vector<NodeID> & packed_path, const PhantomNodes & phantom_node_pair, std::vector<PathData> & unpacked_path) const
|
|
|
|
{
|
2014-03-25 13:06:05 -04:00
|
|
|
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);
|
2014-03-10 10:36:58 -04:00
|
|
|
|
2013-09-20 07:08:18 -04:00
|
|
|
const unsigned packed_path_size = packed_path.size();
|
|
|
|
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
|
|
//We have to push the path in reverse order onto the stack because it's LIFO.
|
2013-09-20 07:08:18 -04:00
|
|
|
for(unsigned i = packed_path_size-1; i > 0; --i){
|
2013-09-20 12:30:47 -04:00
|
|
|
recursion_stack.push(
|
|
|
|
std::make_pair(packed_path[i-1], packed_path[i])
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<NodeID, NodeID> edge;
|
2014-04-25 09:48:10 -04:00
|
|
|
while (!recursion_stack.empty())
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
edge = recursion_stack.top();
|
|
|
|
recursion_stack.pop();
|
2012-06-15 12:47:27 -04:00
|
|
|
|
2014-02-27 13:49:53 -05:00
|
|
|
// 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;
|
2014-04-25 09:48:10 -04:00
|
|
|
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
|
|
|
{
|
2014-02-27 13:49:53 -05:00
|
|
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
2014-04-25 09:48:10 -04:00
|
|
|
if ((facade->GetTarget(edge_id) == edge.second) &&
|
2014-02-27 13:49:53 -05:00
|
|
|
(weight < edge_weight) &&
|
2014-04-25 09:48:10 -04:00
|
|
|
facade->GetEdgeData(edge_id).forward)
|
|
|
|
{
|
2014-02-27 13:49:53 -05:00
|
|
|
smaller_edge_id = edge_id;
|
|
|
|
edge_weight = weight;
|
|
|
|
}
|
|
|
|
}
|
2014-04-25 09:48:10 -04:00
|
|
|
if (SPECIAL_EDGEID == smaller_edge_id)
|
|
|
|
{
|
|
|
|
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
|
|
|
{
|
2014-02-27 13:49:53 -05:00
|
|
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
2014-04-25 09:48:10 -04:00
|
|
|
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
|
|
|
{
|
2014-02-27 13:49:53 -05:00
|
|
|
smaller_edge_id = edge_id;
|
|
|
|
edge_weight = weight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-25 09:48:10 -04:00
|
|
|
BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid");
|
2014-02-27 13:49:53 -05:00
|
|
|
|
2014-04-25 09:48:10 -04:00
|
|
|
const EdgeData & ed = facade->GetEdgeData(smaller_edge_id);
|
|
|
|
if (ed.shortcut)
|
|
|
|
{//unpack
|
2013-09-20 07:08:18 -04:00
|
|
|
const NodeID middle_node_id = ed.id;
|
2012-06-15 12:47:27 -04:00
|
|
|
//again, we need to this in reversed order
|
2013-09-20 07:08:18 -04:00
|
|
|
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
|
|
|
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
2014-04-25 09:48:10 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-02-11 05:42:24 -05:00
|
|
|
BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
|
|
|
|
unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
|
2014-02-26 09:55:04 -05:00
|
|
|
const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id);
|
2014-02-21 10:55:41 -05:00
|
|
|
|
2014-04-25 09:48:10 -04:00
|
|
|
if (!facade->EdgeIsCompressed(ed.id))
|
|
|
|
{
|
2014-02-11 05:42:24 -05:00
|
|
|
BOOST_ASSERT( !facade->EdgeIsCompressed(ed.id) );
|
|
|
|
unpacked_path.push_back(
|
|
|
|
PathData(
|
|
|
|
facade->GetGeometryIndexForEdgeID(ed.id),
|
|
|
|
name_index,
|
|
|
|
turn_instruction,
|
|
|
|
ed.distance
|
|
|
|
)
|
|
|
|
);
|
2014-04-25 09:48:10 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-02-11 05:42:24 -05:00
|
|
|
std::vector<unsigned> id_vector;
|
2014-02-28 11:14:38 -05:00
|
|
|
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id), id_vector);
|
2014-02-11 05:42:24 -05:00
|
|
|
|
2014-03-25 13:06:05 -04:00
|
|
|
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 );
|
2014-02-27 13:49:53 -05:00
|
|
|
const int end_index = id_vector.size();
|
2014-04-25 09:48:10 -04:00
|
|
|
|
|
|
|
BOOST_ASSERT(start_index >= 0);
|
|
|
|
BOOST_ASSERT(start_index <= end_index);
|
|
|
|
for (int i = start_index; i < end_index; ++i)
|
|
|
|
{
|
2014-02-27 13:49:53 -05:00
|
|
|
unpacked_path.push_back(
|
|
|
|
PathData(
|
|
|
|
id_vector[i],
|
|
|
|
name_index,
|
|
|
|
TurnInstructionsClass::NoTurn,
|
|
|
|
0
|
|
|
|
)
|
|
|
|
);
|
2014-02-11 05:42:24 -05:00
|
|
|
}
|
2014-05-07 12:39:16 -04:00
|
|
|
unpacked_path.back().turn_instruction = turn_instruction;
|
|
|
|
unpacked_path.back().segment_duration = ed.distance;
|
2014-02-11 05:42:24 -05:00
|
|
|
}
|
2012-06-15 12:47:27 -04:00
|
|
|
}
|
|
|
|
}
|
2014-04-25 09:48:10 -04:00
|
|
|
if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
|
|
|
|
{
|
2014-02-28 11:14:38 -05:00
|
|
|
std::vector<unsigned> id_vector;
|
2014-03-25 13:06:05 -04:00
|
|
|
facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id, id_vector);
|
2014-04-25 09:48:10 -04:00
|
|
|
if (target_traversed_in_reverse)
|
|
|
|
{
|
2014-03-03 12:47:34 -05:00
|
|
|
std::reverse(id_vector.begin(), id_vector.end() );
|
|
|
|
}
|
2014-03-25 13:06:05 -04:00
|
|
|
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id == phantom_node_pair.target_phantom.packed_geometry_id) && unpacked_path.empty();
|
2014-03-12 12:23:21 -04:00
|
|
|
|
|
|
|
int start_index = 0;
|
2014-03-25 13:06:05 -04:00
|
|
|
int end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
2014-03-12 12:23:21 -04:00
|
|
|
if (target_traversed_in_reverse)
|
|
|
|
{
|
2014-03-25 13:06:05 -04:00
|
|
|
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
|
2014-03-12 12:23:21 -04:00
|
|
|
}
|
|
|
|
if (is_local_path)
|
|
|
|
{
|
2014-03-25 13:06:05 -04:00
|
|
|
start_index = phantom_node_pair.source_phantom.fwd_segment_position;
|
|
|
|
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
2014-03-12 12:23:21 -04:00
|
|
|
if (target_traversed_in_reverse)
|
|
|
|
{
|
2014-03-25 13:06:05 -04:00
|
|
|
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;
|
2014-03-12 12:23:21 -04:00
|
|
|
}
|
|
|
|
}
|
2014-03-03 12:47:34 -05:00
|
|
|
|
2014-04-25 09:48:10 -04:00
|
|
|
BOOST_ASSERT(start_index >= 0);
|
|
|
|
for (int i = start_index; i != end_index; (start_index < end_index ? ++i :--i))
|
|
|
|
{
|
2014-03-19 11:42:37 -04:00
|
|
|
BOOST_ASSERT( i >= -1 );
|
2014-02-28 11:14:38 -05:00
|
|
|
unpacked_path.push_back(
|
|
|
|
PathData(
|
|
|
|
id_vector[i],
|
2014-03-25 13:06:05 -04:00
|
|
|
phantom_node_pair.target_phantom.name_id,
|
2014-02-28 11:14:38 -05:00
|
|
|
TurnInstructionsClass::NoTurn,
|
|
|
|
0
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2014-03-28 13:25:35 -04:00
|
|
|
|
|
|
|
// 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());
|
2014-03-28 12:13:00 -04:00
|
|
|
}
|
2012-06-15 12:47:27 -04:00
|
|
|
}
|
|
|
|
|
2014-04-25 09:48:10 -04:00
|
|
|
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpacked_path) const
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
|
|
|
recursion_stack.push(std::make_pair(s,t));
|
2012-06-21 06:27:43 -04:00
|
|
|
|
|
|
|
std::pair<NodeID, NodeID> edge;
|
2014-04-25 09:48:10 -04:00
|
|
|
while (!recursion_stack.empty())
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
edge = recursion_stack.top();
|
|
|
|
recursion_stack.pop();
|
2012-06-21 06:27:43 -04:00
|
|
|
|
2013-09-20 07:08:18 -04:00
|
|
|
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
|
|
|
int edge_weight = INT_MAX;
|
2014-04-25 09:48:10 -04:00
|
|
|
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
|
|
|
{
|
2013-09-24 04:10:50 -04:00
|
|
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
2013-09-20 07:08:18 -04:00
|
|
|
if(
|
2013-09-24 04:10:50 -04:00
|
|
|
(facade->GetTarget(edge_id) == edge.second) &&
|
2013-09-20 07:08:18 -04:00
|
|
|
(weight < edge_weight) &&
|
2013-09-24 04:10:50 -04:00
|
|
|
facade->GetEdgeData(edge_id).forward
|
2013-09-20 07:08:18 -04:00
|
|
|
){
|
2013-09-24 04:10:50 -04:00
|
|
|
smaller_edge_id = edge_id;
|
2013-09-20 07:08:18 -04:00
|
|
|
edge_weight = weight;
|
2012-06-21 06:27:43 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-25 09:48:10 -04:00
|
|
|
if (SPECIAL_EDGEID == smaller_edge_id)
|
|
|
|
{
|
|
|
|
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
|
|
|
{
|
2013-09-24 04:10:50 -04:00
|
|
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
2014-04-25 09:48:10 -04:00
|
|
|
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
|
|
|
{
|
2013-09-24 04:10:50 -04:00
|
|
|
smaller_edge_id = edge_id;
|
2013-09-20 07:08:18 -04:00
|
|
|
edge_weight = weight;
|
2012-06-21 06:27:43 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-20 07:08:18 -04:00
|
|
|
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
|
2012-06-21 06:27:43 -04:00
|
|
|
|
2013-09-24 04:10:50 -04:00
|
|
|
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
2014-04-25 09:48:10 -04:00
|
|
|
if (ed.shortcut)
|
|
|
|
{//unpack
|
2013-09-20 07:08:18 -04:00
|
|
|
const NodeID middle_node_id = ed.id;
|
2012-06-21 06:27:43 -04:00
|
|
|
//again, we need to this in reversed order
|
2014-04-25 09:48:10 -04:00
|
|
|
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
|
|
|
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-09-20 05:35:59 -04:00
|
|
|
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
|
2013-09-20 07:08:18 -04:00
|
|
|
unpacked_path.push_back(edge.first );
|
2012-06-21 06:27:43 -04:00
|
|
|
}
|
|
|
|
}
|
2013-09-20 07:08:18 -04:00
|
|
|
unpacked_path.push_back(t);
|
2012-06-21 06:27:43 -04:00
|
|
|
}
|
|
|
|
|
2013-09-19 12:53:34 -04:00
|
|
|
inline void RetrievePackedPathFromHeap(
|
2014-02-26 09:55:04 -05:00
|
|
|
const SearchEngineData::QueryHeap & forward_heap,
|
|
|
|
const SearchEngineData::QueryHeap & reverse_heap,
|
2013-09-20 07:08:18 -04:00
|
|
|
const NodeID middle_node_id,
|
|
|
|
std::vector<NodeID> & packed_path
|
2014-04-25 09:48:10 -04:00
|
|
|
) const
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
NodeID current_node_id = middle_node_id;
|
2014-04-25 09:48:10 -04:00
|
|
|
while(current_node_id != forward_heap.GetData(current_node_id).parent)
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
current_node_id = forward_heap.GetData(current_node_id).parent;
|
|
|
|
packed_path.push_back(current_node_id);
|
2012-06-15 12:47:27 -04:00
|
|
|
}
|
2013-09-20 07:08:18 -04:00
|
|
|
std::reverse(packed_path.begin(), packed_path.end());
|
|
|
|
packed_path.push_back(middle_node_id);
|
|
|
|
current_node_id = middle_node_id;
|
2014-04-25 09:48:10 -04:00
|
|
|
while (current_node_id != reverse_heap.GetData(current_node_id).parent)
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
current_node_id = reverse_heap.GetData(current_node_id).parent;
|
|
|
|
packed_path.push_back(current_node_id);
|
2012-09-27 13:46:44 -04:00
|
|
|
}
|
2012-06-15 12:47:27 -04:00
|
|
|
}
|
2013-02-03 10:47:32 -05:00
|
|
|
|
2013-09-20 07:08:18 -04:00
|
|
|
inline void RetrievePackedPathFromSingleHeap(
|
2014-04-25 09:48:10 -04:00
|
|
|
const SearchEngineData::QueryHeap & search_heap,
|
2013-09-20 07:08:18 -04:00
|
|
|
const NodeID middle_node_id,
|
|
|
|
std::vector<NodeID>& packed_path
|
2014-04-25 09:48:10 -04:00
|
|
|
) const
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
NodeID current_node_id = middle_node_id;
|
2014-04-25 09:48:10 -04:00
|
|
|
while(current_node_id != search_heap.GetData(current_node_id).parent)
|
|
|
|
{
|
2013-09-20 07:08:18 -04:00
|
|
|
current_node_id = search_heap.GetData(current_node_id).parent;
|
|
|
|
packed_path.push_back(current_node_id);
|
2013-02-03 10:47:32 -05:00
|
|
|
}
|
|
|
|
}
|
2012-06-15 12:47:27 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* BASICROUTINGINTERFACE_H_ */
|