[routing] Implemented osrm router with our indexes.

This commit is contained in:
Denis Koronchik 2014-09-11 13:22:40 +03:00 committed by Alex Zolotarev
parent ac916226a1
commit 4e61179f07
7 changed files with 362 additions and 252 deletions

View file

@ -164,6 +164,7 @@ template <class DataFacadeT> class BasicRoutingInterface
recursion_stack.emplace(packed_path[i - 1], packed_path[i]);
}
unpacked_path.emplace_back(packed_path[0], INVALID_EDGE_WEIGHT, TurnInstruction::NoTurn, INVALID_EDGE_WEIGHT);
std::pair<NodeID, NodeID> edge;
while (!recursion_stack.empty())
{
@ -224,87 +225,91 @@ template <class DataFacadeT> class BasicRoutingInterface
}
else
{
BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id);
if (!facade->EdgeIsCompressed(ed.id))
{
BOOST_ASSERT(!facade->EdgeIsCompressed(ed.id));
unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id),
name_index,
turn_instruction,
ed.distance);
}
else
{
std::vector<unsigned> id_vector;
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id),
id_vector);
const std::size_t 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);
const std::size_t end_index = id_vector.size();
BOOST_ASSERT(start_index >= 0);
BOOST_ASSERT(start_index <= end_index);
for (std::size_t i = start_index; i < end_index; ++i)
{
unpacked_path.emplace_back(id_vector[i], name_index, TurnInstruction::NoTurn, 0);
}
unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().segment_duration = ed.distance;
}
}
}
if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
{
std::vector<unsigned> id_vector;
facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id,
id_vector);
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
phantom_node_pair.target_phantom.packed_geometry_id) &&
unpacked_path.empty();
std::size_t start_index = 0;
if (is_local_path)
{
start_index = phantom_node_pair.source_phantom.fwd_segment_position;
if (target_traversed_in_reverse)
{
start_index =
id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
}
}
std::size_t end_index = phantom_node_pair.target_phantom.fwd_segment_position;
if (target_traversed_in_reverse)
{
std::reverse(id_vector.begin(), id_vector.end());
end_index =
id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
}
if (start_index > end_index)
{
start_index = std::min(start_index, id_vector.size()-1);
}
SimpleLogger().Write() << "start_index: " << start_index << ", end_index: " << end_index;
for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
{
BOOST_ASSERT(i < id_vector.size());
unpacked_path.emplace_back(PathData{id_vector[i],
phantom_node_pair.target_phantom.name_id,
unpacked_path.emplace_back(edge.second,
INVALID_EDGE_WEIGHT,
TurnInstruction::NoTurn,
0});
INVALID_EDGE_WEIGHT);
// BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
// unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
// const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id);
// if (!facade->EdgeIsCompressed(ed.id))
// {
// BOOST_ASSERT(!facade->EdgeIsCompressed(ed.id));
// unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id),
// name_index,
// turn_instruction,
// ed.distance);
// }
// else
// {
// std::vector<unsigned> id_vector;
// facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id),
// id_vector);
// const std::size_t 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);
// const std::size_t end_index = id_vector.size();
// BOOST_ASSERT(start_index >= 0);
// BOOST_ASSERT(start_index <= end_index);
// for (std::size_t i = start_index; i < end_index; ++i)
// {
// unpacked_path.emplace_back(id_vector[i], name_index, TurnInstruction::NoTurn, 0);
// }
// unpacked_path.back().turn_instruction = turn_instruction;
// unpacked_path.back().segment_duration = ed.distance;
// }
}
}
// if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
// {
// std::vector<unsigned> id_vector;
// facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id,
// id_vector);
// const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
// phantom_node_pair.target_phantom.packed_geometry_id) &&
// unpacked_path.empty();
// std::size_t start_index = 0;
// if (is_local_path)
// {
// start_index = phantom_node_pair.source_phantom.fwd_segment_position;
// if (target_traversed_in_reverse)
// {
// start_index =
// id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
// }
// }
// std::size_t end_index = phantom_node_pair.target_phantom.fwd_segment_position;
// if (target_traversed_in_reverse)
// {
// std::reverse(id_vector.begin(), id_vector.end());
// end_index =
// id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
// }
// if (start_index > end_index)
// {
// start_index = std::min(start_index, id_vector.size()-1);
// }
// SimpleLogger().Write() << "start_index: " << start_index << ", end_index: " << end_index;
// for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
// {
// BOOST_ASSERT(i < id_vector.size());
// unpacked_path.emplace_back(PathData{id_vector[i],
// phantom_node_pair.target_phantom.name_id,
// TurnInstruction::NoTurn,
// 0});
// }
// }
// 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

View file

@ -254,7 +254,7 @@ Framework::Framework()
LOG(LDEBUG, ("Guides info initialized"));
#endif
m_routingSession.SetRouter(new routing::OsrmRouter());
m_routingSession.SetRouter(new routing::OsrmRouter(&m_model.GetIndex()));
LOG(LINFO, ("System languages:", languages::GetPreferred()));
}

View file

@ -18,12 +18,9 @@
namespace routing
{
#define NOT_IMPLEMENTED { assert(false); }
template <class EdgeDataT> class OsrmDataFacade : public BaseDataFacade<EdgeDataT>
{
typedef BaseDataFacade<EdgeDataT> super;
typedef typename super::RTreeLeaf RTreeLeaf;
boost::iostreams::mapped_file_source m_edgeDataSource;
succinct::gamma_vector m_edgeData;
@ -37,18 +34,6 @@ template <class EdgeDataT> class OsrmDataFacade : public BaseDataFacade<EdgeData
unsigned m_numberOfNodes;
// --- OSRM ---
std::shared_ptr< vector<FixedPointCoordinate> > m_coordinateList;
vector<NodeID> m_viaNodeList;
vector<TurnInstruction> m_turnInstructionList;
vector<unsigned> m_nameIDList;
vector<bool> m_egdeIsCompressed;
vector<unsigned> m_geometryIndices;
vector<unsigned> m_geometryList;
//RangeTable<16, false> m_name_table;
//vector<char> m_names_char_list;
StaticRTree<RTreeLeaf, vector<FixedPointCoordinate> > *m_staticRTree;
public:
template <typename T>
void loadFromFile(T & v, string const & fileName)
@ -60,7 +45,6 @@ public:
}
OsrmDataFacade(string const & fileName)
: m_staticRTree(0)
{
m_edgeDataSource.open(fileName + ".edgedata");
succinct::mapper::map(m_edgeData, m_edgeDataSource);
@ -77,22 +61,10 @@ public:
//std::cout << m_fanoMatrix.size() << std::endl;
m_numberOfNodes = (unsigned)sqrt(m_fanoMatrix.size() / 2) + 1;
// --- OSRM ---
// load data
LoadNodeAndEdgeInformation(fileName + ".nodes", fileName + ".edges");
LoadGeometries(fileName + ".geometry");
//LoadStreetNames(fileName + ".names");
boost::filesystem::path ram_index_path(fileName + ".ramIndex");
boost::filesystem::path file_index_path(fileName + ".fileIndex");
m_staticRTree = new StaticRTree<RTreeLeaf, vector<FixedPointCoordinate> >(ram_index_path, file_index_path, m_coordinateList);
}
~OsrmDataFacade()
{
delete m_staticRTree;
m_edgeDataSource.close();
m_edgeIdSource.close();
m_shortcutsSource.close();
@ -192,60 +164,51 @@ public:
EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const
{
NOT_IMPLEMENTED;
return (EdgeID)0;
}
EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const
{
NOT_IMPLEMENTED;
return (EdgeID)0;
}
// node and edge information access
FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const
{
return m_coordinateList->at(id);
return FixedPointCoordinate();
}
bool EdgeIsCompressed(const unsigned id) const
{
assert(id < m_egdeIsCompressed.size());
return m_egdeIsCompressed[id];
return false;
}
unsigned GetGeometryIndexForEdgeID(const unsigned id) const
{
return m_viaNodeList.at(id);
return false;
}
void GetUncompressedGeometry(const unsigned id, std::vector<unsigned> &result_nodes) const
{
const unsigned begin = m_geometryIndices.at(id);
const unsigned end = m_geometryIndices.at(id + 1);
result_nodes.clear();
result_nodes.insert(result_nodes.begin(), m_geometryList.begin() + begin, m_geometryList.begin() + end);
}
TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const
{
return m_turnInstructionList[id];
return TurnInstruction::NoTurn;
}
bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
FixedPointCoordinate &result,
const unsigned zoom_level = 18)
{
return m_staticRTree->LocateClosestEndPointForCoordinate(input_coordinate, result, zoom_level);
return false;
}
bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
PhantomNode &resulting_phantom_node,
const unsigned zoom_level)
{
return m_staticRTree->FindPhantomNodeForCoordinate(input_coordinate, resulting_phantom_node, zoom_level);
return false;
}
bool IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
@ -253,120 +216,32 @@ public:
const unsigned zoom_level,
const unsigned number_of_results)
{
NOT_IMPLEMENTED;
return false;
}
unsigned GetCheckSum() const
{
NOT_IMPLEMENTED;
return 0;
}
unsigned GetNameIndexFromEdgeID(const unsigned id) const
{
return m_nameIDList.at(id);
return -1;
}
void GetName(const unsigned name_id, std::string &result) const
{
NOT_IMPLEMENTED;
}
std::string GetEscapedNameForNameID(const unsigned name_id) const
{
std::string temporary_string;
GetName(name_id, temporary_string);
return EscapeJSONString(temporary_string);
return std::string();
}
std::string GetTimestamp() const
{
return "";
}
// ------------------- OSRM ------------------------
void LoadNodeAndEdgeInformation(string const & nodesFile, string const & edgesFile)
{
std::ifstream nodes_input_stream(nodesFile, std::ios::binary);
NodeInfo current_node;
unsigned number_of_coordinates = 0;
nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
m_coordinateList = std::make_shared< std::vector<FixedPointCoordinate> >(number_of_coordinates);
for (unsigned i = 0; i < number_of_coordinates; ++i)
{
nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
m_coordinateList->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
}
nodes_input_stream.close();
std::ifstream edges_input_stream(edgesFile, std::ios::binary);
unsigned number_of_edges = 0;
edges_input_stream.read((char *)&number_of_edges, sizeof(unsigned));
m_viaNodeList.resize(number_of_edges);
m_nameIDList.resize(number_of_edges);
m_turnInstructionList.resize(number_of_edges);
m_egdeIsCompressed.resize(number_of_edges);
unsigned compressed = 0;
OriginalEdgeData current_edge_data;
for (unsigned i = 0; i < number_of_edges; ++i)
{
edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData));
m_viaNodeList[i] = current_edge_data.via_node;
m_nameIDList[i] = current_edge_data.name_id;
m_turnInstructionList[i] = current_edge_data.turn_instruction;
m_egdeIsCompressed[i] = current_edge_data.compressed_geometry;
if (m_egdeIsCompressed[i])
{
++compressed;
}
}
edges_input_stream.close();
}
void LoadGeometries(string const & geometry_file)
{
std::ifstream geometry_stream(geometry_file, std::ios::binary);
unsigned number_of_indices = 0;
unsigned number_of_compressed_geometries = 0;
geometry_stream.read((char *)&number_of_indices, sizeof(unsigned));
m_geometryIndices.resize(number_of_indices);
if (number_of_indices > 0)
geometry_stream.read((char *)&(m_geometryIndices[0]), number_of_indices * sizeof(unsigned));
geometry_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
BOOST_ASSERT(m_geometryIndices.back() == number_of_compressed_geometries);
m_geometryList.resize(number_of_compressed_geometries);
if (number_of_compressed_geometries > 0)
geometry_stream.read((char *)&(m_geometryList[0]), number_of_compressed_geometries * sizeof(unsigned));
geometry_stream.close();
}
/*void LoadStreetNames(string const & namesFile)
{
std::ifstream name_stream(namesFile, std::ios::binary);
name_stream >> m_name_table;
unsigned number_of_chars = 0;
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
ASSERT(0 != number_of_chars, "name file broken");
m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element
name_stream.read((char *)&m_names_char_list[0], number_of_chars * sizeof(char));
name_stream.close();
}*/
};
}

View file

@ -1,10 +1,14 @@
#pragma once
#include "../base/assert.hpp"
#include "../base/logging.hpp"
#include "../std/string.hpp"
#include "../std/vector.hpp"
#include "../std/fstream.hpp"
#include "../std/unordered_map.hpp"
#include "../std/sstream.hpp"
namespace routing
{
@ -21,6 +25,26 @@ public:
uint32_t m_fid;
uint32_t m_pointStart;
uint32_t m_pointEnd;
FtSeg()
: m_fid(-1), m_pointStart(-1), m_pointEnd(-1)
{
}
FtSeg(uint32_t fid, uint32_t ps, uint32_t pe)
: m_fid(fid), m_pointStart(ps), m_pointEnd(pe)
{
}
friend string DebugPrint(FtSeg const & seg)
{
stringstream ss;
ss << "{ fID = " << seg.m_fid <<
"; pStart = " << seg.m_pointStart <<
"; pEnd = " << seg.m_pointEnd << " }";
return ss.str();
}
};
typedef vector<FtSeg> FtSegVectorT;
@ -89,24 +113,47 @@ public:
return it->second;
}
void DumpSegments(uint32_t fID) const
{
LOG(LINFO, ("Dump segments for feature:", fID));
for (auto it = m_osrm2FtSeg.begin(); it != m_osrm2FtSeg.end(); ++it)
for (auto s : it->second)
if (s.m_fid == fID)
LOG(LINFO, (s));
}
void GetOsrmNode(FtSeg const & seg, OsrmNodeIdT & forward, OsrmNodeIdT & reverse) const
{
ASSERT_LESS(seg.m_pointStart, seg.m_pointEnd, ());
forward = SPECIAL_OSRM_NODE_ID;
reverse = SPECIAL_OSRM_NODE_ID;
for (unordered_map<OsrmNodeIdT, FtSegVectorT>::const_iterator it = m_osrm2FtSeg.begin(); it != m_osrm2FtSeg.end(); ++it)
for (auto it = m_osrm2FtSeg.begin(); it != m_osrm2FtSeg.end(); ++it)
{
/// @todo Do break in production here when both are found.
for (auto s : it->second)
{
if (s.m_fid != seg.m_fid)
continue;
if (s.m_pointStart <= s.m_pointEnd)
{
if (seg.m_pointStart >= s.m_pointStart && seg.m_pointEnd <= s.m_pointEnd)
{
ASSERT_EQUAL(forward, SPECIAL_OSRM_NODE_ID, ());
forward = it->first;
}
}
else
{
if (seg.m_pointStart >= s.m_pointEnd && seg.m_pointEnd <= s.m_pointStart)
{
ASSERT_EQUAL(reverse, SPECIAL_OSRM_NODE_ID, ());
reverse = it->first;
}
}
}
}

View file

@ -1,20 +1,113 @@
#include "osrm_router.hpp"
#include "osrm_data_facade.hpp"
#include "route.hpp"
#include "vehicle_model.hpp"
#include "../geometry/distance.hpp"
#include "../indexer/mercator.hpp"
#include "../indexer/index.hpp"
#include "../platform/platform.hpp"
#include "../3party/osrm/osrm-backend/DataStructures/SearchEngine.h"
#include "../base/logging.hpp"
#include "../3party/osrm/osrm-backend/DataStructures/SearchEngineData.h"
#include "../3party/osrm/osrm-backend/DataStructures/QueryEdge.h"
#include "../3party/osrm/osrm-backend/Descriptors/DescriptionFactory.h"
#include "../3party/osrm/osrm-backend/RoutingAlgorithms/ShortestPathRouting.h"
namespace routing
{
#define FACADE_READ_ZOOM_LEVEL 13
class Point2PhantomNode
{
m2::PointD m_point;
double m_minDist;
uint32_t m_segIdx;
FeatureID m_fID;
OsrmFtSegMapping const & m_mapping;
CarModel m_carModel;
public:
Point2PhantomNode(m2::PointD const & pt, OsrmFtSegMapping const & mapping)
: m_point(pt), m_minDist(numeric_limits<double>::max()), m_segIdx(-1), m_mapping(mapping)
{
}
void operator() (FeatureType const & ft)
{
if (ft.GetFeatureType() != feature::GEOM_LINE || m_carModel.GetSpeed(ft) == 0)
return;
ft.ParseGeometry(FeatureType::BEST_GEOMETRY);
size_t const count = ft.GetPointsCount();
ASSERT_GREATER(count, 1, ());
for (size_t i = 1; i < count; ++i)
{
m2::DistanceToLineSquare<m2::PointD> segDist;
segDist.SetBounds(ft.GetPoint(i - 1), ft.GetPoint(i));
double const d = segDist(m_point);
if (d < m_minDist)
{
m_minDist = d;
m_fID = ft.GetID();
m_segIdx = i - 1;
}
}
}
bool HasFeature() const
{
return m_fID.IsValid();
}
bool MakeResult(PhantomNode & resultNode, uint32_t & mwmId)
{
ASSERT(m_fID.IsValid(), ());
resultNode.forward_node_id = resultNode.reverse_node_id = -1;
OsrmFtSegMapping::FtSeg seg;
seg.m_fid = m_fID.m_offset;
seg.m_pointStart = m_segIdx;
seg.m_pointEnd = m_segIdx + 1;
m_mapping.GetOsrmNode(seg, resultNode.forward_node_id, resultNode.reverse_node_id);
mwmId = m_fID.m_mwm;
if (resultNode.forward_node_id == -1 && resultNode.reverse_node_id == -1)
{
LOG(LINFO, ("Can't find osrm node", seg));
m_mapping.DumpSegments(seg.m_fid);
return false;
}
else
return true;
}
size_t GetMwmID() const
{
return m_fID.m_mwm;
}
};
// ----------------
OsrmRouter::OsrmRouter(Index const * index)
: m_pIndex(index)
{
}
string OsrmRouter::GetName() const
{
return "mapsme";
@ -25,71 +118,147 @@ void OsrmRouter::SetFinalPoint(m2::PointD const & finalPt)
m_finalPt = finalPt;
}
namespace
{
class MakeResultGuard
{
IRouter::ReadyCallback const & m_callback;
Route m_route;
string m_errorMsg;
public:
MakeResultGuard(IRouter::ReadyCallback const & callback, string const & name)
: m_callback(callback), m_route(name)
{
}
~MakeResultGuard()
{
if (!m_errorMsg.empty())
LOG(LINFO, ("Failed calculate route", m_errorMsg));
m_callback(m_route);
}
void SetErrorMsg(char const * msg) { m_errorMsg = msg; }
void SetGeometry(vector<m2::PointD> const & vec)
{
m_route.SetGeometry(vec.begin(), vec.end());
m_errorMsg.clear();
}
};
}
void OsrmRouter::CalculateRoute(m2::PointD const & startingPt, ReadyCallback const & callback)
{
typedef OsrmDataFacade<QueryEdge::EdgeData> DataFacadeT;
#ifdef OMIM_OS_DESKTOP
DataFacadeT facade("/Users/deniskoronchik/Documents/develop/omim-maps/Belarus.osrm");
m_mapping.Load("/Users/deniskoronchik/Documents/develop/omim-maps/Belarus.osrm.ftseg");
#else
DataFacadeT facade(GetPlatform().WritablePathForFile("Belarus.osrm"));
m_mapping.Load(GetPlatform().WritablePathForFile("Belarus.osrm.ftseg");
#endif
SearchEngine<DataFacadeT> engine(&facade);
SearchEngineData engine_working_data;
ShortestPathRouting<DataFacadeT> shortest_path(&facade, engine_working_data);
RawRouteData rawRoute;
PhantomNodes nodes;
MakeResultGuard resGuard(callback, GetName());
uint32_t mwmIdStart = -1;
if (!FindPhantomNode(startingPt, nodes.source_phantom, mwmIdStart))
{
resGuard.SetErrorMsg("Can't find start point");
return;
}
uint32_t mwmIdEnd = -1;
if (!FindPhantomNode(m_finalPt, nodes.target_phantom, mwmIdEnd))
{
resGuard.SetErrorMsg("Can't find end point");
return;
}
if (mwmIdEnd != mwmIdStart || mwmIdEnd == -1 || mwmIdStart == -1)
{
resGuard.SetErrorMsg("Points in different MWMs");
return;
}
FixedPointCoordinate startPoint((int)(MercatorBounds::YToLat(startingPt.y) * COORDINATE_PRECISION),
(int)(MercatorBounds::XToLon(startingPt.x) * COORDINATE_PRECISION));
facade.FindPhantomNodeForCoordinate(startPoint, nodes.source_phantom, 18);
//FACADE_READ_ZOOM_LEVEL);
FixedPointCoordinate endPoint((int)(MercatorBounds::YToLat(m_finalPt.y) * COORDINATE_PRECISION),
(int)(MercatorBounds::XToLon(m_finalPt.x) * COORDINATE_PRECISION));
facade.FindPhantomNodeForCoordinate(endPoint, nodes.target_phantom, 18);
//FACADE_READ_ZOOM_LEVEL);
rawRoute.raw_via_node_coordinates = {startPoint, endPoint};
rawRoute.raw_via_node_coordinates = { startPoint, endPoint };
rawRoute.segment_end_coordinates.push_back(nodes);
engine.shortest_path({nodes}, {}, rawRoute);
shortest_path({nodes}, {}, rawRoute);
Route route(GetName());
if (INVALID_EDGE_WEIGHT == rawRoute.shortest_path_length
|| rawRoute.segment_end_coordinates.empty()
|| rawRoute.source_traversed_in_reverse.empty())
{
callback(route);
resGuard.SetErrorMsg("Route not found");
return;
}
// restore route
DescriptionFactory factory;
factory.SetStartSegment(rawRoute.segment_end_coordinates.front().source_phantom,
rawRoute.source_traversed_in_reverse.front());
// for each unpacked segment add the leg to the description
for (auto const i : osrm::irange<std::size_t>(0, rawRoute.unpacked_path_segments.size()))
{
unsigned added_element_count = 0;
// Get all the coordinates for the computed route
FixedPointCoordinate current_coordinate;
for (PathData const & path_data : rawRoute.unpacked_path_segments[i])
{
current_coordinate = facade.GetCoordinateOfNode(path_data.node);
factory.AppendSegment(current_coordinate, path_data);
++added_element_count;
}
factory.SetEndSegment(rawRoute.segment_end_coordinates[i].target_phantom, rawRoute.target_traversed_in_reverse[i]);
++added_element_count;
ASSERT_EQUAL((rawRoute.unpacked_path_segments[i].size() + 1), added_element_count, ());
}
factory.Run(&facade, FACADE_READ_ZOOM_LEVEL);
factory.BuildRouteSummary(factory.entireLength, rawRoute.shortest_path_length);
vector<m2::PointD> points;
for (auto const si : factory.path_description)
points.push_back(m2::PointD(MercatorBounds::LonToX(si.location.lon / COORDINATE_PRECISION), MercatorBounds::LatToY(si.location.lat / COORDINATE_PRECISION))); // @todo: possible need convert to mercator
route.SetGeometry(points.begin(), points.end());
for (auto i : osrm::irange<std::size_t>(0, rawRoute.unpacked_path_segments.size()))
{
// Get all the coordinates for the computed route
for (PathData const & path_data : rawRoute.unpacked_path_segments[i])
{
OsrmFtSegMapping::FtSegVectorT const & v = m_mapping.GetSegVector(path_data.node);
for (OsrmFtSegMapping::FtSeg seg : v)
{
FeatureType ft;
Index::FeaturesLoaderGuard loader(*m_pIndex, mwmIdStart);
loader.GetFeature(seg.m_fid, ft);
ft.ParseGeometry(FeatureType::BEST_GEOMETRY);
callback(route);
if (seg.m_pointEnd > seg.m_pointStart)
{
for (auto j = seg.m_pointStart; j <= seg.m_pointEnd; ++j)
points.push_back(ft.GetPoint(j));
}
else
{
for (auto j = seg.m_pointStart; j > seg.m_pointEnd; --j)
points.push_back(ft.GetPoint(j));
points.push_back(ft.GetPoint(seg.m_pointEnd));
}
}
}
}
resGuard.SetGeometry(points);
}
bool OsrmRouter::FindPhantomNode(m2::PointD const & pt, PhantomNode & resultNode, uint32_t & mwmId)
{
double radius = 100.0;
Point2PhantomNode getter(pt, m_mapping);
while (radius < 1000.0)
{
m_pIndex->ForEachInRect(getter,
MercatorBounds::RectByCenterXYAndSizeInMeters(pt, radius),
17); /// @todo Pass minimal scale when ALL roads are visible.
if (getter.HasFeature())
return getter.MakeResult(resultNode, mwmId);
else
radius += 100;
}
return false;
}
}

View file

@ -1,6 +1,10 @@
#pragma once
#include "router.hpp"
#include "osrm_data_facade_types.hpp"
class Index;
class PhantomNode;
namespace routing
{
@ -10,9 +14,19 @@ class OsrmRouter : public IRouter
m2::PointD m_finalPt;
public:
OsrmRouter(Index const * index);
virtual string GetName() const;
virtual void SetFinalPoint(m2::PointD const & finalPt);
virtual void CalculateRoute(m2::PointD const & startingPt, ReadyCallback const & callback);
protected:
bool FindPhantomNode(m2::PointD const & pt, PhantomNode & resultNode, uint32_t & mwmId);
private:
Index const * m_pIndex;
OsrmFtSegMapping m_mapping;
};

View file

@ -16,7 +16,7 @@ void Callback(Route const & r)
UNIT_TEST(OsrmRouter_Test)
{
OsrmRouter router;
/*OsrmRouter router;
router.SetFinalPoint(m2::PointD(MercatorBounds::LonToX(27.54334), MercatorBounds::LatToY(53.899338))); // офис Немига
router.CalculateRoute(m2::PointD(MercatorBounds::LonToX(27.6704144), MercatorBounds::LatToY(53.9456243)), Callback); // Городецкая
router.CalculateRoute(m2::PointD(MercatorBounds::LonToX(27.6704144), MercatorBounds::LatToY(53.9456243)), Callback); // Городецкая*/
}