forked from organicmaps/organicmaps
[routing] Implemented osrm router with our indexes.
This commit is contained in:
parent
ac916226a1
commit
4e61179f07
7 changed files with 362 additions and 252 deletions
|
@ -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
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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 *)¤t_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();
|
||||
}*/
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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); // Городецкая*/
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue