[generator] Add mapping from Fid to graph node id (not finished)

This commit is contained in:
Denis Koronchik 2014-09-03 16:08:28 +03:00 committed by Alex Zolotarev
parent 59214f805d
commit a7bf5cf36f
8 changed files with 429 additions and 122 deletions

View file

@ -41,6 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph_origin,
std::unique_ptr<RestrictionMap> restriction_map,
std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_node_list,
@ -49,6 +50,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
: speed_profile(speed_profile),
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
m_node_info_list(m_node_info_list), m_node_based_graph(node_based_graph),
m_node_based_graph_origin(node_based_graph_origin),
m_restriction_map(std::move(restriction_map)), max_id(0)
{
@ -77,7 +79,7 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
nodes.swap(m_edge_based_node_list);
}
void EdgeBasedGraphFactory::GetEdgeBasedNodeData(std::vector<NodeData> &data)
void EdgeBasedGraphFactory::GetEdgeBasedNodeData(osrm::NodeDataVectorT &data)
{
data.swap(m_edge_based_node_data);
}
@ -269,10 +271,6 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
RenumberEdges();
TIMER_STOP(renumber);
TIMER_START(generate_node_data);
GenerateEdgeBasedNodeData();
TIMER_STOP(generate_node_data);
TIMER_START(generate_nodes);
GenerateEdgeExpandedNodes();
TIMER_STOP(generate_nodes);
@ -281,6 +279,11 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state);
TIMER_STOP(generate_edges);
TIMER_START(generate_node_data);
GenerateEdgeBasedNodeData();
TIMER_STOP(generate_node_data);
m_geometry_compressor.SerializeInternalVector(geometry_filename);
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
@ -477,6 +480,8 @@ void EdgeBasedGraphFactory::RenumberEdges()
void EdgeBasedGraphFactory::GenerateEdgeBasedNodeData()
{
BOOST_ASSERT(m_node_based_graph->GetNumberOfNodes() == m_node_based_graph_origin->GetNumberOfNodes());
m_edge_based_node_data.resize(m_number_of_edge_based_nodes);
std::vector<bool> found;
found.resize(m_number_of_edge_based_nodes, false);
@ -486,21 +491,59 @@ void EdgeBasedGraphFactory::GenerateEdgeBasedNodeData()
{
for (EdgeID current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
{
EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge);
EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge);
if (!edge_data.forward)
{
continue;
}
NodeID target = m_node_based_graph->GetTarget(current_edge);
NodeData data;
data.lat1 = m_node_info_list[current_node].lat / COORDINATE_PRECISION;
data.lon1 = m_node_info_list[current_node].lon / COORDINATE_PRECISION;
osrm::NodeData data;
if (m_geometry_compressor.HasEntryForID(current_edge))
{
const std::vector<GeometryCompressor::CompressedNode> & via_nodes = m_geometry_compressor.GetBucketReference(current_edge);
assert(via_nodes.size() > 0);
std::vector< std::pair< NodeID, FixedPointCoordinate > > nodes;
for (auto n : via_nodes)
nodes.emplace_back(n.first, FixedPointCoordinate(m_node_info_list[n.first].lat, m_node_info_list[n.first].lon));
data.lat2 = m_node_info_list[target].lat / COORDINATE_PRECISION;
data.lon2 = m_node_info_list[target].lon / COORDINATE_PRECISION;
for (uint32_t i = 0; i < nodes.size() - 1; ++i)
{
auto n1 = nodes[i];
auto n2 = nodes[i + 1];
data.way_id = edge_data.way_id;
if (n1.first == n2.first)
{
SimpleLogger().Write() << "Error: Equal values " << n1.first << " and " << n2.first;
SimpleLogger().Write() << "i: "<< i << " nodes: " << nodes.size();
throw std::exception();
}
EdgeID e = m_node_based_graph_origin->FindEdge(n1.first, n2.first);
if (e == SPECIAL_EDGEID)
{
SimpleLogger().Write() << "Error: Can't find edge between nodes " << n1.first << " and " << n2.first;
continue;
}
EdgeData &ed = m_node_based_graph_origin->GetEdgeData(e);
data.AddSegment(ed.way_id,
m_node_info_list[n1.first].lat / COORDINATE_PRECISION,
m_node_info_list[n1.first].lon / COORDINATE_PRECISION,
m_node_info_list[n2.first].lat / COORDINATE_PRECISION,
m_node_info_list[n2.first].lon / COORDINATE_PRECISION);
}
} else
{
data.AddSegment(edge_data.way_id,
m_node_info_list[current_node].lat / COORDINATE_PRECISION,
m_node_info_list[current_node].lon / COORDINATE_PRECISION,
m_node_info_list[target].lat / COORDINATE_PRECISION,
m_node_info_list[target].lon / COORDINATE_PRECISION);
}
if (found[edge_data.edgeBasedNodeID])
{
@ -692,6 +735,16 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
BOOST_ASSERT(edge_data1.forward);
BOOST_ASSERT(edge_data2.forward);
if (edge_data1.way_id == 244396524)
{
SimpleLogger().Write() << " - Id: " << edge_data1.way_id << " n1: " << u << " n2: " << v;
}
if (edge_data2.way_id == 244396524)
{
SimpleLogger().Write() << " - Id: " << edge_data2.way_id << " n1: " << v << " n2: " << w;
}
// the following is the core of the loop.
unsigned distance = edge_data1.distance;
if (m_traffic_lights.find(v) != m_traffic_lights.end())

View file

@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/TurnInstructions.h"
#include "../DataStructures/NodeBasedGraph.h"
#include "../DataStructures/RestrictionMap.h"
#include "../DataStructures/EdgeBasedNodeData.h"
#include "GeometryCompressor.h"
#include <algorithm>
@ -49,6 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unordered_set>
#include <vector>
struct lua_State;
class EdgeBasedGraphFactory
@ -57,27 +59,10 @@ class EdgeBasedGraphFactory
EdgeBasedGraphFactory() = delete;
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
struct NodeData
{
double lat1, lon1;
double lat2, lon2;
unsigned way_id;
bool operator == (NodeData const & other)
{
return (way_id == other.way_id) && (lat1 == other.lat1) && (lon1 == other.lon1)
&& (lat2 == other.lat2) && (lon2 == other.lon2);
}
bool operator != (NodeData const & other)
{
return !(*this == other);
}
};
struct SpeedProfileProperties;
explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph_origin,
std::unique_ptr<RestrictionMap> restricion_map,
std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_node_list,
@ -92,7 +77,7 @@ class EdgeBasedGraphFactory
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
void GetEdgeBasedNodeData(std::vector<NodeData> &data);
void GetEdgeBasedNodeData(osrm::NodeDataVectorT &data);
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, double angle) const;
@ -122,11 +107,12 @@ class EdgeBasedGraphFactory
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph_origin;
std::unordered_set<NodeID> m_barrier_nodes;
std::unordered_set<NodeID> m_traffic_lights;
std::unique_ptr<RestrictionMap> m_restriction_map;
std::vector<NodeData> m_edge_based_node_data;
std::vector<osrm::NodeData> m_edge_based_node_data;
GeometryCompressor m_geometry_compressor;

View file

@ -493,8 +493,13 @@ void Prepare::BuildEdgeExpandedGraph(lua_State *lua_state,
NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
std::unique_ptr<RestrictionMap> restriction_map =
std::unique_ptr<RestrictionMap>(new RestrictionMap(node_based_graph, restriction_list));
std::shared_ptr<NodeBasedDynamicGraph> node_based_graph_origin =
NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
EdgeBasedGraphFactory *edge_based_graph_factory =
new EdgeBasedGraphFactory(node_based_graph,
node_based_graph_origin,
std::move(restriction_map),
barrier_node_list,
traffic_light_list,
@ -524,22 +529,12 @@ void Prepare::BuildEdgeExpandedGraph(lua_State *lua_state,
edge_based_graph_factory->GetEdgeBasedNodes(node_based_edge_list);
// serialize node data
std::vector<EdgeBasedGraphFactory::NodeData> data;
osrm::NodeDataVectorT data;
edge_based_graph_factory->GetEdgeBasedNodeData(data);
SimpleLogger().Write() << "Serialize node data";
std::ofstream stream;
stream.open(node_data_filename);
if (!stream.is_open())
{
SimpleLogger().Write() << "Can't open file " << node_data_filename;
throw std::exception();
}
uint32_t count = data.size();
stream.write((const char*)&count, sizeof(count));
stream.write((const char*)(&data[0]), data.size() * sizeof(EdgeBasedGraphFactory::NodeData));
stream.close();
osrm::SaveNodeDataToFile(node_data_filename, data);
delete edge_based_graph_factory;

View file

@ -0,0 +1,123 @@
#pragma once
#include <stdint.h>
#include <vector>
#include <fstream>
namespace osrm
{
struct NodeData
{
#pragma pack (push, 1)
struct SegmentInfo
{
uint64_t wayId;
double lat1, lon1, lat2, lon2;
SegmentInfo()
: wayId(-1), lat1(-10000), lon1(-10000), lat2(-10000), lon2(-10000)
{
}
SegmentInfo(uint64_t wayId, double lat1, double lon1, double lat2, double lon2)
: wayId(wayId), lat1(lat1), lon1(lon1), lat2(lat2), lon2(lon2)
{
}
bool operator != (SegmentInfo const & other) const
{
return wayId != other.wayId || lat1 != other.lat1 || lon1 != other.lon1 ||
lat2 != other.lat2 || lon2 != other.lon2;
}
};
#pragma pack (pop)
typedef std::vector<SegmentInfo> SegmentInfoVectorT;
SegmentInfoVectorT m_segments;
NodeData()
{
}
NodeData(SegmentInfoVectorT & vec)
{
m_segments.swap(vec);
}
bool operator == (NodeData const & other) const
{
if (m_segments.size() != other.m_segments.size())
return false;
for (uint32_t i = 0; i < m_segments.size(); ++i)
if (m_segments[i] != other.m_segments[i])
return false;
return true;
}
bool operator != (NodeData const & other) const
{
return !(*this == other);
}
void AddSegment(uint64_t wayId, double lat1, double lon1, double lat2, double lon2)
{
m_segments.emplace_back(wayId, lat1, lon1, lat2, lon2);
}
void SetSegments(SegmentInfoVectorT & segments)
{
m_segments.swap(segments);
}
};
typedef std::vector<NodeData> NodeDataVectorT;
inline bool SaveNodeDataToFile(std::string const & filename, NodeDataVectorT const & data)
{
std::ofstream stream;
stream.open(filename);
if (!stream.is_open())
return false;
uint32_t count = data.size();
stream.write((char*)&count, sizeof(count));
for (auto d : data)
{
uint32_t pc = d.m_segments.size();
stream.write((char*)&pc, sizeof(pc));
stream.write((char*)d.m_segments.data(), sizeof(NodeData::SegmentInfo) * pc);
}
stream.close();
return true;
}
inline bool LoadNodeDataFromFile(std::string const & filename, NodeDataVectorT & data)
{
std::ifstream stream;
stream.open(filename);
if (!stream.is_open())
return false;
uint32_t count = 0;
stream.read((char*)&count, sizeof(count));
for (uint32_t i = 0; i < count; ++i)
{
uint32_t pc;
stream.read((char*)&pc, sizeof(pc));
NodeData::SegmentInfoVectorT segments;
segments.resize(pc);
stream.read((char*)segments.data(), sizeof(NodeData::SegmentInfo) * pc);
data.emplace_back(segments);
}
stream.close();
return true;
}
}

View file

@ -1,39 +1,30 @@
#include "routing_generator.hpp"
#include "gen_mwm_info.hpp"
#include "../indexer/index.hpp"
#include "../indexer/classificator_loader.hpp"
#include "../indexer/feature.hpp"
#include "../indexer/ftypes_matcher.hpp"
#include "../indexer/mercator.hpp"
#include "../geometry/distance_on_sphere.hpp"
#include "../routing/osrm_data_facade_types.hpp"
#include "../platform/platform.hpp"
#include "../base/logging.hpp"
#include "../std/fstream.hpp"
#include "../3party/osrm/osrm-backend/DataStructures/EdgeBasedNodeData.h"
#include "../3party/osrm/osrm-backend/DataStructures/QueryEdge.h"
#include "../3party/osrm/osrm-backend/Server/DataStructures/InternalDataFacade.h"
namespace routing
{
uint32_t const MAX_SCALE = 15; // max scale for roads
struct Node2Feature
{
NodeID m_nodeId;
FeatureID m_FID;
uint32_t m_start;
uint32_t m_len;
Node2Feature(NodeID nodeId, FeatureID fid, uint32_t start, uint32_t len)
: m_nodeId(nodeId), m_FID(fid), m_start(start), m_len(len)
{
}
};
struct Node2FeatureSetComp
{
bool operator() (Node2Feature const & a, Node2Feature const & b)
{
return a.m_nodeId < b.m_nodeId;
}
};
typedef std::set<Node2Feature, Node2FeatureSetComp> Node2FeatureSet;
double const EQUAL_POINT_RADIUS_M = 1;
void GenerateNodesInfo(string const & mwmName, string const & osrmName)
{
@ -47,73 +38,110 @@ void GenerateNodesInfo(string const & mwmName, string const & osrmName)
return;
}
ServerPaths server_paths;
server_paths["hsgrdata"] = boost::filesystem::path(osrmName + ".hsgr");
server_paths["ramindex"] = boost::filesystem::path(osrmName + ".ramIndex");
server_paths["fileindex"] = boost::filesystem::path(osrmName + ".fileIndex");
server_paths["geometries"] = boost::filesystem::path(osrmName + ".geometry");
server_paths["nodesdata"] = boost::filesystem::path(osrmName + ".nodes");
server_paths["edgesdata"] = boost::filesystem::path(osrmName + ".edges");
server_paths["namesdata"] = boost::filesystem::path(osrmName + ".names");
server_paths["timestamp"] = boost::filesystem::path(osrmName + ".timestamp");
Platform & pl = GetPlatform();
InternalDataFacade<QueryEdge::EdgeData> facade(server_paths);
Node2FeatureSet nodesSet;
uint32_t processed = 0;
auto fn = [&](FeatureType const & ft)
gen::OsmID2FeatureID osm2ft;
{
processed++;
ReaderSource<ModelReaderPtr> src(pl.GetReader(mwmName + OSM2FEATURE_FILE_EXTENSION));
osm2ft.Read(src);
}
if (processed % 1000 == 0)
string nodeFileName = osrmName + ".nodeData";
OsrmFtSegMapping mapping;
ifstream input;
input.open(nodeFileName);
if (!input.is_open())
{
LOG(LERROR, ("Can't open file ", nodeFileName));
return;
}
osrm::NodeDataVectorT nodeData;
if (!osrm::LoadNodeDataFromFile(nodeFileName, nodeData))
{
LOG(LERROR, ("Can't load node data"));
return;
}
uint32_t found = 0, all = 0;
uint32_t nodeId = 0;
for (osrm::NodeData data : nodeData)
{
uint32_t segId = 0;
OsrmFtSegMapping::FtSegVectorT vec;
vec.resize(data.m_segments.size());
for (auto seg : data.m_segments)
{
if (processed % 10000 == 0)
std::cout << "[" << processed / 1000 << "k]";
else
std::cout << ".";
std::cout.flush();
}
m2::PointD pts[2] = {{seg.lon1, seg.lat1}, {seg.lon2, seg.lat2}};
feature::TypesHolder types(ft);
if (types.GetGeoType() != feature::GEOM_LINE)
return;
all++;
if (!ftypes::IsStreetChecker::Instance()(ft))
return;
std::cout << "------------ FID: " << ft.GetID().m_offset << std::endl;
ft.ParseGeometry(FeatureType::BEST_GEOMETRY);
uint32_t lastId = std::numeric_limits<uint32_t>::max();
uint32_t start = 0;
for (uint32_t i = 1; i < ft.GetPointsCount(); ++i)
{
m2::PointD p = ft.GetPoint(i -1).mid(ft.GetPoint(i));
FixedPointCoordinate fp(static_cast<int>(p.x * COORDINATE_PRECISION),
static_cast<int>(p.y * COORDINATE_PRECISION));
PhantomNode node;
if (facade.FindPhantomNodeForCoordinate(fp, node, 18))
// now need to determine feature id and segments in it
uint32_t const fID = osm2ft.GetFeatureID(seg.wayId);
if (fID == 0)
{
if (node.forward_node_id != lastId)
LOG(LWARNING, ("No feature id for way:", seg.wayId));
continue;
}
FeatureType ft;
Index::FeaturesLoaderGuard loader(index, 0);
loader.GetFeature(fID, ft);
ft.ParseGeometry(FeatureType::BEST_GEOMETRY);
int32_t indicies[2] = {-1, -1};
for (uint32_t j = 0; j < ft.GetPointsCount(); ++j)
{
double lon = MercatorBounds::XToLon(ft.GetPoint(j).x);
double lat = MercatorBounds::YToLat(ft.GetPoint(j).y);
for (uint32_t k = 0; k < 2; ++k)
{
if (lastId != std::numeric_limits<uint32_t>::max())
double const dist = ms::DistanceOnEarth(pts[k].y, pts[k].x, lat, lon);
//LOG(LINFO, ("Distance: ", dist));
if (dist <= EQUAL_POINT_RADIUS_M)
{
bool added = nodesSet.insert(Node2Feature(node.forward_node_id, ft.GetID(), start, i - 1)).second;
assert(added);
//ASSERT_EQUAL(indicies[k], -1, ());
indicies[k] = j;
}
lastId = node.forward_node_id;
start = i - 1;
std::cout << "LastID: " << lastId << " ForwardID: " << node.forward_node_id << " Offset: " << node.forward_offset << std::endl;
}
} else
break;
}
// Check if indicies found
if (indicies[0] != -1 && indicies[1] != -1)
{
found++;
ASSERT_NOT_EQUAL(indicies[0], indicies[1], ());
OsrmFtSegMapping::FtSeg & segData = vec[segId++];
segData.m_fid = fID;
segData.m_pointEnd = indicies[1];
segData.m_pointStart = indicies[0];
mapping.Append(nodeId++, vec);
}
else
{
LOG(LINFO, ("----------------- Way ID: ", seg.wayId, "--- Segments: ", data.m_segments.size(), " SegId: ", segId));
LOG(LINFO, ("P1: ", pts[0].y, " ", pts[0].x, " P2: ", pts[1].y, " ", pts[1].x));
for (uint32_t j = 0; j < ft.GetPointsCount(); ++j)
{
double lon = MercatorBounds::XToLon(ft.GetPoint(j).x);
double lat = MercatorBounds::YToLat(ft.GetPoint(j).y);
double const dist1 = ms::DistanceOnEarth(pts[0].y, pts[0].x, lat, lon);
double const dist2 = ms::DistanceOnEarth(pts[1].y, pts[1].x, lat, lon);
LOG(LINFO, ("p", j, ": ", lat, ", ", lon, " Dist1: ", dist1, " Dist2: ", dist2));
}
}
}
};
index.ForEachInRect(fn, MercatorBounds::FullRect(), MAX_SCALE);
std::cout << "Nodes: " << facade.GetNumberOfNodes() << " Set: " << nodesSet.size() << std::endl;
}
LOG(LINFO, ("Found: ", found, " All: ", all));
mapping.Save(osrmName + ".ftseg");
}
}

View file

@ -1,9 +1,11 @@
#pragma once
#include "../std/string.hpp"
#include "../std/vector.hpp"
namespace routing
{
void GenerateNodesInfo(string const & mwmName, string const & osrmName);
}

View file

@ -0,0 +1,119 @@
#pragma once
#include "../base/assert.hpp"
#include "../std/string.hpp"
#include "../std/vector.hpp"
#include "../std/fstream.hpp"
#include "../std/unordered_map.hpp"
namespace routing
{
#define SPECIAL_OSRM_NODE_ID -1
typedef uint32_t OsrmNodeIdT;
class OsrmFtSegMapping
{
public:
struct FtSeg
{
uint32_t m_fid;
uint32_t m_pointStart;
uint32_t m_pointEnd;
};
typedef vector<FtSeg> FtSegVectorT;
void Save(string const & filename)
{
ofstream stream;
stream.open(filename);
if (!stream.is_open())
return;
uint32_t count = m_osrm2FtSeg.size();
stream.write((char*)&count, sizeof(count));
for (uint32_t i = 0; i < count; ++i)
{
auto it = m_osrm2FtSeg.find(i);
CHECK(it != m_osrm2FtSeg.end(), ());
FtSegVectorT const & v = it->second;
uint32_t vc = v.size();
stream.write((char*)&vc, sizeof(vc));
stream.write((char*)v.data(), sizeof(OsrmFtSegMapping::FtSeg) * vc);
}
stream.close();
}
void Load(string const & filename)
{
ifstream stream;
stream.open(filename);
if (!stream.is_open())
return;
uint32_t count = 0;
stream.read((char*)&count, sizeof(count));
for (uint32_t i = 0; i < count; ++i)
{
uint32_t vc = 0;
stream.read((char*)&vc, sizeof(vc));
FtSegVectorT v;
v.resize(vc);
stream.read((char*)v.data(), sizeof(FtSeg) * vc);
m_osrm2FtSeg[i] = v;
}
stream.close();
}
void Append(OsrmNodeIdT osrmNodeId, FtSegVectorT & data)
{
ASSERT(m_osrm2FtSeg.find(osrmNodeId) == m_osrm2FtSeg.end(), ());
m_osrm2FtSeg[osrmNodeId] = data;
}
FtSegVectorT const & GetSegVector(OsrmNodeIdT nodeId) const
{
auto it = m_osrm2FtSeg.find(nodeId);
ASSERT(it != m_osrm2FtSeg.end(), ());
return it->second;
}
void GetOsrmNode(FtSeg const & seg, OsrmNodeIdT & forward, OsrmNodeIdT & reverse) const
{
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 s : it->second)
{
if (s.m_pointStart <= s.m_pointEnd)
{
if (seg.m_pointStart >= s.m_pointStart && seg.m_pointEnd <= s.m_pointEnd)
forward = it->first;
}
else
{
if (seg.m_pointStart >= s.m_pointEnd && seg.m_pointEnd <= s.m_pointStart)
reverse = it->first;
}
}
}
}
private:
unordered_map<OsrmNodeIdT, FtSegVectorT> m_osrm2FtSeg;
};
}

View file

@ -31,6 +31,7 @@ HEADERS += \
osrm_router.hpp \
osrm_online_router.hpp \
osrm_data_facade.hpp \
osrm_data_facade_types.hpp \
road_graph_router.hpp \
dijkstra_router.hpp \
features_road_graph.hpp \