forked from organicmaps/organicmaps
[OpenLR] Assemble all things together. Cache edges within one run.
This commit is contained in:
parent
2be0781941
commit
774e6930d8
11 changed files with 356 additions and 54 deletions
|
@ -17,8 +17,6 @@ void CandidatePointsGetter::GetJunctionPointCandidates(m2::PointD const & p,
|
|||
// Or start with small radius and scale it up when there are too few points.
|
||||
size_t const kRectSideMeters = 110;
|
||||
|
||||
auto const mwmId = m_mwmIdByPointFn(p);
|
||||
|
||||
auto const rect = MercatorBounds::RectByCenterXYAndSizeInMeters(p, kRectSideMeters);
|
||||
auto const selectCandidates = [&rect, &candidates](FeatureType & ft) {
|
||||
ft.ParseGeometry(FeatureType::BEST_GEOMETRY);
|
||||
|
@ -45,11 +43,7 @@ void CandidatePointsGetter::GetJunctionPointCandidates(m2::PointD const & p,
|
|||
},
|
||||
[](m2::PointD const & a, m2::PointD const & b) { return a == b; });
|
||||
|
||||
LOG(LDEBUG,
|
||||
(candidates.size(), "candidate points are found for point", MercatorBounds::ToLatLon(p)));
|
||||
candidates.resize(min(m_maxJunctionCandidates, candidates.size()));
|
||||
LOG(LDEBUG,
|
||||
(candidates.size(), "candidates points are remained for point", MercatorBounds::ToLatLon(p)));
|
||||
}
|
||||
|
||||
void CandidatePointsGetter::EnrichWithProjectionPoints(m2::PointD const & p,
|
||||
|
@ -58,7 +52,7 @@ void CandidatePointsGetter::EnrichWithProjectionPoints(m2::PointD const & p,
|
|||
m_graph.ResetFakes();
|
||||
|
||||
vector<pair<Graph::Edge, Junction>> vicinities;
|
||||
m_graph.FindClosestEdges(p, m_maxProjectionCandidates, vicinities);
|
||||
m_graph.FindClosestEdges(p, static_cast<uint32_t>(m_maxProjectionCandidates), vicinities);
|
||||
for (auto const & v : vicinities)
|
||||
{
|
||||
auto const & edge = v.first;
|
||||
|
@ -75,10 +69,11 @@ void CandidatePointsGetter::EnrichWithProjectionPoints(m2::PointD const & p,
|
|||
auto const firstHalf = Edge::MakeFake(edge.GetStartJunction(), junction, edge);
|
||||
auto const secondHalf = Edge::MakeFake(junction, edge.GetEndJunction(), edge);
|
||||
|
||||
m_graph.AddOutgoingFakeEdge(firstHalf);
|
||||
m_graph.AddIngoingFakeEdge(firstHalf);
|
||||
m_graph.AddOutgoingFakeEdge(secondHalf);
|
||||
m_graph.AddIngoingFakeEdge(secondHalf);
|
||||
candidates.push_back(junction.GetPoint());
|
||||
}
|
||||
LOG(LDEBUG, (vicinities.size(), "projections candidates were added"));
|
||||
}
|
||||
} // namespace openlr
|
||||
|
|
|
@ -15,18 +15,13 @@ namespace openlr
|
|||
{
|
||||
class CandidatePointsGetter
|
||||
{
|
||||
using MwmIdByPointFn = std::function<MwmSet::MwmId(m2::PointD const &)>;
|
||||
|
||||
public:
|
||||
CandidatePointsGetter(size_t const maxJunctionCandidates, size_t const maxProjectionCandidates,
|
||||
Index const & index, MwmIdByPointFn const & mwmIdByPointFn, Graph & graph,
|
||||
v2::Stats & stat)
|
||||
Index const & index, Graph & graph)
|
||||
: m_maxJunctionCandidates(maxJunctionCandidates)
|
||||
, m_maxProjectionCandidates(maxProjectionCandidates)
|
||||
, m_index(index)
|
||||
, m_mwmIdByPointFn(mwmIdByPointFn)
|
||||
, m_graph(graph)
|
||||
, m_stat(stat)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -45,7 +40,5 @@ private:
|
|||
|
||||
Index const & m_index;
|
||||
Graph & m_graph;
|
||||
v2::Stats & m_stat;
|
||||
MwmIdByPointFn m_mwmIdByPointFn;
|
||||
};
|
||||
} // namespace openlr
|
||||
|
|
|
@ -6,32 +6,58 @@ using namespace routing;
|
|||
|
||||
namespace openlr
|
||||
{
|
||||
namespace
|
||||
{
|
||||
using EdgeGetter = void (IRoadGraph::*)(Junction const &, RoadGraphBase::TEdgeVector &) const;
|
||||
|
||||
void GetRegularEdges(Junction const & junction, IRoadGraph const & graph,
|
||||
EdgeGetter const edgeGetter,
|
||||
map<openlr::Graph::Junction, Graph::EdgeVector> & cache,
|
||||
Graph::EdgeVector & edges)
|
||||
{
|
||||
auto const it = cache.find(junction);
|
||||
if (it == end(cache))
|
||||
{
|
||||
auto & es = cache[junction];
|
||||
(graph.*edgeGetter)(junction, es);
|
||||
edges.insert(end(edges), begin(es), end(es));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const & es = it->second;
|
||||
edges.insert(end(edges), begin(es), end(es));
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Graph::Graph(Index const & index, shared_ptr<CarModelFactory> carModelFactory)
|
||||
: m_graph(index, IRoadGraph::Mode::ObeyOnewayTag, carModelFactory)
|
||||
{
|
||||
}
|
||||
|
||||
void Graph::GetOutgoingEdges(Junction const & junction, EdgeVector & edges) const
|
||||
void Graph::GetOutgoingEdges(Junction const & junction, EdgeVector & edges)
|
||||
{
|
||||
m_graph.GetOutgoingEdges(junction, edges);
|
||||
GetRegularOutgoingEdges(junction, edges);
|
||||
m_graph.GetFakeOutgoingEdges(junction, edges);
|
||||
}
|
||||
|
||||
void Graph::GetIngoingEdges(Junction const & junction, EdgeVector & edges) const
|
||||
void Graph::GetIngoingEdges(Junction const & junction, EdgeVector & edges)
|
||||
{
|
||||
m_graph.GetIngoingEdges(junction, edges);
|
||||
GetRegularIngoingEdges(junction, edges);
|
||||
m_graph.GetFakeIngoingEdges(junction, edges);
|
||||
}
|
||||
|
||||
void Graph::GetRegularOutgoingEdges(Junction const & junction, EdgeVector & edges) const
|
||||
void Graph::GetRegularOutgoingEdges(Junction const & junction, EdgeVector & edges)
|
||||
{
|
||||
m_graph.GetRegularOutgoingEdges(junction, edges);
|
||||
GetRegularEdges(junction, m_graph, &IRoadGraph::GetRegularOutgoingEdges, m_outgoingCache, edges);
|
||||
}
|
||||
|
||||
void Graph::GetRegularIngoingEdges(Junction const & junction, EdgeVector & edges) const
|
||||
void Graph::GetRegularIngoingEdges(Junction const & junction, EdgeVector & edges)
|
||||
{
|
||||
m_graph.GetRegularIngoingEdges(junction, edges);
|
||||
GetRegularEdges(junction, m_graph, &IRoadGraph::GetRegularIngoingEdges, m_ingoingCache, edges);
|
||||
}
|
||||
|
||||
void Graph::FindClosestEdges(m2::PointD const & point, uint32_t count,
|
||||
void Graph::FindClosestEdges(m2::PointD const & point, uint32_t const count,
|
||||
vector<pair<Edge, Junction>> & vicinities) const
|
||||
{
|
||||
m_graph.FindClosestEdges(point, count, vicinities);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
@ -25,13 +26,19 @@ public:
|
|||
|
||||
Graph(Index const & index, std::shared_ptr<routing::CarModelFactory> carModelFactory);
|
||||
|
||||
void GetOutgoingEdges(routing::Junction const & junction, EdgeVector & edges) const;
|
||||
void GetIngoingEdges(routing::Junction const & junction, EdgeVector & edges) const;
|
||||
// Appends edges such as that edge.GetStartJunction() == junction to the |edges|.
|
||||
void GetOutgoingEdges(routing::Junction const & junction, EdgeVector & edges);
|
||||
// Appends edges such as that edge.GetEndJunction() == junction to the |edges|.
|
||||
void GetIngoingEdges(routing::Junction const & junction, EdgeVector & edges);
|
||||
|
||||
void GetRegularIngoingEdges(Junction const & junction, EdgeVector & edges) const;
|
||||
void GetRegularOutgoingEdges(Junction const & junction, EdgeVector & edges) const;
|
||||
// Appends edges such as that edge.GetStartJunction() == junction and edge.IsFake() == false
|
||||
// to the |edges|.
|
||||
void GetRegularOutgoingEdges(Junction const & junction, EdgeVector & edges);
|
||||
// Appends edges such as that edge.GetEndJunction() == junction and edge.IsFale() == false
|
||||
// to the |edges|.
|
||||
void GetRegularIngoingEdges(Junction const & junction, EdgeVector & edges);
|
||||
|
||||
void FindClosestEdges(m2::PointD const & point, uint32_t count,
|
||||
void FindClosestEdges(m2::PointD const & point, uint32_t const count,
|
||||
std::vector<pair<Edge, Junction>> & vicinities) const;
|
||||
|
||||
void AddFakeEdges(Junction const & junction,
|
||||
|
@ -44,5 +51,7 @@ public:
|
|||
|
||||
private:
|
||||
routing::FeaturesRoadGraph m_graph;
|
||||
std::map<Junction, EdgeVector> m_outgoingCache;
|
||||
std::map<Junction, EdgeVector> m_ingoingCache;
|
||||
};
|
||||
} // namespace openlr
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
#include "openlr/openlr_decoder.hpp"
|
||||
|
||||
#include "openlr/candidate_paths_getter.hpp"
|
||||
#include "openlr/candidate_points_getter.hpp"
|
||||
#include "openlr/decoded_path.hpp"
|
||||
#include "openlr/graph.hpp"
|
||||
#include "openlr/helpers.hpp"
|
||||
#include "openlr/openlr_model.hpp"
|
||||
#include "openlr/paths_connector.hpp"
|
||||
#include "openlr/road_info_getter.hpp"
|
||||
#include "openlr/router.hpp"
|
||||
#include "openlr/way_point.hpp"
|
||||
|
@ -14,13 +19,27 @@
|
|||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/index.hpp"
|
||||
|
||||
#include "storage/country_info_getter.hpp"
|
||||
|
||||
#include "platform/country_file.hpp"
|
||||
|
||||
#include "geometry/point2d.hpp"
|
||||
#include "geometry/polyline2d.hpp"
|
||||
|
||||
#include "base/logging.hpp"
|
||||
#include "base/math.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
#include "base/timer.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
using namespace routing;
|
||||
using namespace std;
|
||||
|
@ -50,6 +69,111 @@ struct alignas(kCacheLineSize) Stats
|
|||
uint32_t m_tightOffsets = 0;
|
||||
uint32_t m_total = 0;
|
||||
};
|
||||
|
||||
bool IsRealVertex(m2::PointD const & p, FeatureID const & fid, Index const & index)
|
||||
{
|
||||
Index::FeaturesLoaderGuard g(index, fid.m_mwmId);
|
||||
auto const ft = g.GetOriginalFeatureByIndex(fid.m_index);
|
||||
bool matched = false;
|
||||
ft->ForEachPoint(
|
||||
[&p, &matched](m2::PointD const & fp) {
|
||||
if (p == fp)
|
||||
matched = true;
|
||||
},
|
||||
FeatureType::BEST_GEOMETRY);
|
||||
return matched;
|
||||
};
|
||||
|
||||
void ExpandFake(Graph::EdgeVector & path, Graph::EdgeVector::iterator edgeIt, Index const & index,
|
||||
Graph & g)
|
||||
{
|
||||
if (!edgeIt->IsFake())
|
||||
return;
|
||||
|
||||
Graph::EdgeVector edges;
|
||||
if (IsRealVertex(edgeIt->GetStartPoint(), edgeIt->GetFeatureId(), index))
|
||||
{
|
||||
g.GetRegularOutgoingEdges(edgeIt->GetStartJunction(), edges);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(IsRealVertex(edgeIt->GetEndPoint(), edgeIt->GetFeatureId(), index), ());
|
||||
g.GetRegularIngoingEdges(edgeIt->GetEndJunction(), edges);
|
||||
}
|
||||
|
||||
CHECK(!edges.empty(), ());
|
||||
|
||||
auto const it = find_if(begin(edges), end(edges), [&edgeIt](Graph::Edge const & real) {
|
||||
if (real.GetFeatureId() == edgeIt->GetFeatureId() && real.GetSegId() == edgeIt->GetSegId())
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
CHECK(it != end(edges), ());
|
||||
|
||||
// If a fake edge is larger than a half of the corresponding real one, substitute
|
||||
// the fake one with real one. Drop the fake one otherwize.
|
||||
if (2 * EdgeLength(*edgeIt) >= EdgeLength(*it))
|
||||
*edgeIt = *it;
|
||||
else
|
||||
path.erase(edgeIt);
|
||||
};
|
||||
|
||||
void ExpandFakes(Index const & index, Graph & g, Graph::EdgeVector & path)
|
||||
{
|
||||
ASSERT(!path.empty(), ());
|
||||
|
||||
ExpandFake(path, begin(path), index, g);
|
||||
ExpandFake(path, --end(path), index, g);
|
||||
}
|
||||
|
||||
// Returns an iterator pointing to the first edge that should not be cut off.
|
||||
// Offsets denote a distance in meters one should travel from the start/end of the path
|
||||
// to some point alog that path and drop everything form the start to that point or from
|
||||
// that point to the end.
|
||||
template <typename InputIterator>
|
||||
InputIterator CutOffset(InputIterator start, InputIterator const stop, uint32_t const offset)
|
||||
{
|
||||
if (offset == 0)
|
||||
return start;
|
||||
|
||||
for (uint32_t distance = 0; start != stop; ++start)
|
||||
{
|
||||
auto const edgeLen = EdgeLength(*start);
|
||||
if (distance <= offset && offset < distance + edgeLen)
|
||||
{
|
||||
// Throw out this edge if (offest - distance) is greater than edgeLength / 2.
|
||||
if (2 * (offset - distance) >= edgeLen)
|
||||
++start;
|
||||
break;
|
||||
}
|
||||
distance += edgeLen;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
void CopyWithoutOffsets(InputIterator const start, InputIterator const stop, OutputIterator out,
|
||||
uint32_t const positiveOffset, uint32_t const negativeOffset)
|
||||
{
|
||||
auto from = start;
|
||||
auto to = stop;
|
||||
|
||||
if (distance(start, stop) > 1)
|
||||
{
|
||||
from = CutOffset(start, stop, positiveOffset);
|
||||
// |to| points past the last edge we need to take.
|
||||
to = CutOffset(reverse_iterator<InputIterator>(stop), reverse_iterator<InputIterator>(start),
|
||||
negativeOffset)
|
||||
.base();
|
||||
}
|
||||
|
||||
if (from >= to)
|
||||
return;
|
||||
|
||||
copy(from, to, out);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// OpenLRDecoder::SegmentsFilter -------------------------------------------------------------
|
||||
|
@ -78,14 +202,14 @@ bool OpenLRDecoder::SegmentsFilter::Matches(LinearSegment const & segment) const
|
|||
}
|
||||
|
||||
// OpenLRDecoder -----------------------------------------------------------------------------
|
||||
OpenLRDecoder::OpenLRDecoder(
|
||||
vector<Index> const & indexes, CountryParentNameGetterFn const & countryParentNameGetterFn)
|
||||
: m_indexes(indexes), m_countryParentNameGetterFn(countryParentNameGetterFn)
|
||||
OpenLRDecoder::OpenLRDecoder(vector<Index> const & indexes,
|
||||
CountryParentNameGetter const & countryParentNameGetter)
|
||||
: m_indexes(indexes), m_countryParentNameGetter(countryParentNameGetter)
|
||||
{
|
||||
}
|
||||
|
||||
void OpenLRDecoder::Decode(vector<LinearSegment> const & segments, uint32_t const numThreads,
|
||||
vector<DecodedPath> & paths)
|
||||
void OpenLRDecoder::DecodeV1(vector<LinearSegment> const & segments, uint32_t const numThreads,
|
||||
vector<DecodedPath> & paths)
|
||||
{
|
||||
double const kOffsetToleranceM = 10;
|
||||
|
||||
|
@ -100,7 +224,7 @@ void OpenLRDecoder::Decode(vector<LinearSegment> const & segments, uint32_t cons
|
|||
auto worker = [&segments, &paths, kBatchSize, kProgressFrequency, kOffsetToleranceM, numThreads,
|
||||
this](size_t threadNum, Index const & index, Stats & stats) {
|
||||
FeaturesRoadGraph roadGraph(index, IRoadGraph::Mode::ObeyOnewayTag,
|
||||
make_unique<CarModelFactory>(m_countryParentNameGetterFn));
|
||||
make_unique<CarModelFactory>(m_countryParentNameGetter));
|
||||
RoadInfoGetter roadInfoGetter(index);
|
||||
Router router(roadGraph, roadInfoGetter);
|
||||
|
||||
|
@ -165,8 +289,8 @@ void OpenLRDecoder::Decode(vector<LinearSegment> const & segments, uint32_t cons
|
|||
|
||||
if (stats.m_total % kProgressFrequency == 0)
|
||||
{
|
||||
LOG(LINFO, ("Thread", threadNum, "processed:", stats.m_total, "failed:",
|
||||
stats.m_routeIsNotCalculated));
|
||||
LOG(LINFO, ("Thread", threadNum, "processed:", stats.m_total,
|
||||
"failed:", stats.m_routeIsNotCalculated));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,4 +315,112 @@ void OpenLRDecoder::Decode(vector<LinearSegment> const & segments, uint32_t cons
|
|||
LOG(LINFO, ("Ambiguous routes:", allStats.m_moreThanOneCandidate));
|
||||
LOG(LINFO, ("Path is not reconstructed:", allStats.m_zeroCanditates));
|
||||
}
|
||||
|
||||
void OpenLRDecoder::DecodeV2(vector<LinearSegment> const & segments,
|
||||
uint32_t const /* numThreads */, vector<DecodedPath> & paths)
|
||||
{
|
||||
ASSERT(!m_indexes.empty(), ());
|
||||
auto const & index = m_indexes.back();
|
||||
|
||||
Graph graph(index, make_unique<CarModelFactory>(m_countryParentNameGetter));
|
||||
|
||||
v2::Stats stat;
|
||||
my::Timer timer;
|
||||
RoadInfoGetter infoGetter(index);
|
||||
for (size_t i = 0; i < segments.size(); ++i)
|
||||
{
|
||||
if (!DecodeSingleSegment(segments[i], index, graph, infoGetter, paths[i], stat))
|
||||
++stat.m_routesFailed;
|
||||
++stat.m_routesHandled;
|
||||
|
||||
if (i % 100 == 0 || i == segments.size() - 1)
|
||||
{
|
||||
LOG(LINFO, (i, "segments are processed in",
|
||||
timer.ElapsedSeconds(),
|
||||
"seconds"));
|
||||
timer.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
LOG(LINFO, ("Total routes handled:", stat.m_routesHandled));
|
||||
LOG(LINFO, ("Failed:", stat.m_routesFailed));
|
||||
LOG(LINFO, ("No candidate lines:", stat.m_noCandidateFound));
|
||||
LOG(LINFO, ("Wrong distance to next point:", stat.m_dnpIsZero));
|
||||
LOG(LINFO, ("Wrong offsets:", stat.m_wrongOffsets));
|
||||
LOG(LINFO, ("No shortest path:", stat.m_noShortestPathFound));
|
||||
}
|
||||
|
||||
bool OpenLRDecoder::DecodeSingleSegment(LinearSegment const & segment, Index const & index,
|
||||
Graph & graph, RoadInfoGetter & infoGetter,
|
||||
DecodedPath & path, v2::Stats & stat)
|
||||
{
|
||||
// TODO(mgsergio): Scale indexes.
|
||||
|
||||
double const kPathLengthTolerance = 0.30;
|
||||
uint32_t const kMaxJunctionCandidates = 10;
|
||||
uint32_t const kMaxProjectionCandidates = 5;
|
||||
|
||||
graph.ResetFakes();
|
||||
|
||||
path.m_segmentId.Set(segment.m_segmentId);
|
||||
|
||||
auto const & points = segment.GetLRPs();
|
||||
vector<vector<Graph::EdgeVector>> lineCandidates;
|
||||
lineCandidates.reserve(points.size());
|
||||
LOG(LDEBUG, ("Decoding segment:", segment.m_segmentId, "with", points.size(), "points"));
|
||||
|
||||
CandidatePointsGetter pointsGetter(kMaxJunctionCandidates, kMaxProjectionCandidates, index, graph);
|
||||
CandidatePathsGetter pathsGetter(pointsGetter, graph, infoGetter, stat);
|
||||
|
||||
if (!pathsGetter.GetLineCandidatesForPoints(points, lineCandidates))
|
||||
return false;
|
||||
|
||||
vector<Graph::EdgeVector> resultPath;
|
||||
PathsConnector connector(kPathLengthTolerance, graph, stat);
|
||||
if (!connector.ConnectCandidates(points, lineCandidates, resultPath))
|
||||
return false;
|
||||
|
||||
Graph::EdgeVector route;
|
||||
for (auto const & part : resultPath)
|
||||
route.insert(end(route), begin(part), end(part));
|
||||
|
||||
uint32_t requiredRouteDistanceM = 0;
|
||||
// Sum app all distances between points. Last point's m_distanceToNextPoint
|
||||
// should be equal to zero, but let's skip it just in case.
|
||||
for (auto it = begin(points); it != prev(end(points)); ++it)
|
||||
requiredRouteDistanceM += it->m_distanceToNextPoint;
|
||||
uint32_t actualRouteDistanceM = 0;
|
||||
for (auto const & e : route)
|
||||
actualRouteDistanceM += EdgeLength(e);
|
||||
|
||||
auto const scale = static_cast<double>(actualRouteDistanceM) / requiredRouteDistanceM;
|
||||
LOG(LDEBUG, ("actualRouteDistance:", actualRouteDistanceM,
|
||||
"requiredRouteDistance:", requiredRouteDistanceM, "scale:", scale));
|
||||
|
||||
auto const positiveOffset =
|
||||
static_cast<uint32_t>(segment.m_locationReference.m_positiveOffsetMeters * scale);
|
||||
auto const negativeOffset =
|
||||
static_cast<uint32_t>(segment.m_locationReference.m_negativeOffsetMeters * scale);
|
||||
|
||||
if (positiveOffset + negativeOffset >= requiredRouteDistanceM)
|
||||
{
|
||||
++stat.m_wrongOffsets;
|
||||
LOG(LINFO, ("Wrong offsets for segment:", segment.m_segmentId));
|
||||
return false;
|
||||
}
|
||||
|
||||
ExpandFakes(index, graph, route);
|
||||
ASSERT(none_of(begin(route), end(route), mem_fn(&Graph::Edge::IsFake)), ());
|
||||
CopyWithoutOffsets(begin(route), end(route), back_inserter(path.m_path), positiveOffset,
|
||||
negativeOffset);
|
||||
|
||||
if (path.m_path.empty())
|
||||
{
|
||||
++stat.m_wrongOffsets;
|
||||
LOG(LINFO, ("Path is empty after offsets cutting. segmentId:", segment.m_segmentId));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace openlr
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "base/exception.hpp"
|
||||
#include "openlr/stats.hpp"
|
||||
|
||||
#include <routing/road_graph.hpp>
|
||||
#include "base/exception.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
@ -19,10 +19,13 @@ struct DecodedPath;
|
|||
|
||||
DECLARE_EXCEPTION(DecoderError, RootException);
|
||||
|
||||
class Graph;
|
||||
class RoadInfoGetter;
|
||||
|
||||
class OpenLRDecoder
|
||||
{
|
||||
public:
|
||||
using CountryParentNameGetterFn = std::function<std::string(std::string const &)>;
|
||||
using CountryParentNameGetter = std::function<std::string(std::string const &)>;
|
||||
|
||||
class SegmentsFilter
|
||||
{
|
||||
|
@ -38,14 +41,20 @@ public:
|
|||
};
|
||||
|
||||
OpenLRDecoder(std::vector<Index> const & indexes,
|
||||
CountryParentNameGetterFn const & countryParentNameGetterFn);
|
||||
CountryParentNameGetter const & countryParentNameGetter);
|
||||
|
||||
// Maps partner segments to mwm paths. |segments| should be sorted by partner id.
|
||||
void Decode(std::vector<LinearSegment> const & segments, uint32_t const numThreads,
|
||||
std::vector<DecodedPath> & paths);
|
||||
void DecodeV1(std::vector<LinearSegment> const & segments, uint32_t const numThreads,
|
||||
std::vector<DecodedPath> & paths);
|
||||
|
||||
void DecodeV2(std::vector<LinearSegment> const & segments, uint32_t const /* numThreads */,
|
||||
std::vector<DecodedPath> & paths);
|
||||
|
||||
private:
|
||||
bool DecodeSingleSegment(LinearSegment const & segment, Index const & index, Graph & g,
|
||||
RoadInfoGetter & inforGetter, DecodedPath & path, v2::Stats & stat);
|
||||
|
||||
std::vector<Index> const & m_indexes;
|
||||
CountryParentNameGetterFn m_countryParentNameGetterFn;
|
||||
CountryParentNameGetter m_countryParentNameGetter;
|
||||
};
|
||||
} // namespace openlr
|
||||
|
|
|
@ -2,14 +2,26 @@
|
|||
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace openlr
|
||||
{
|
||||
// LinearSegment -----------------------------------------------------------------------------------
|
||||
std::vector<m2::PointD> LinearSegment::GetMercatorPoints() const
|
||||
vector<m2::PointD> LinearSegment::GetMercatorPoints() const
|
||||
{
|
||||
std::vector<m2::PointD> points;
|
||||
vector<m2::PointD> points;
|
||||
for (auto const & point : m_locationReference.m_points)
|
||||
points.push_back(MercatorBounds::FromLatLon(point.m_latLon));
|
||||
return points;
|
||||
}
|
||||
|
||||
vector<LocationReferencePoint> const & LinearSegment::GetLRPs() const
|
||||
{
|
||||
return m_locationReference.m_points;
|
||||
}
|
||||
|
||||
vector<LocationReferencePoint> & LinearSegment::GetLRPs()
|
||||
{
|
||||
return m_locationReference.m_points;
|
||||
}
|
||||
} // namespace openlr
|
||||
|
|
|
@ -97,6 +97,8 @@ struct LinearSegment
|
|||
static auto constexpr kInvalidSegmentId = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
std::vector<m2::PointD> GetMercatorPoints() const;
|
||||
std::vector<LocationReferencePoint> const & GetLRPs() const;
|
||||
std::vector<LocationReferencePoint> & GetLRPs();
|
||||
|
||||
// TODO(mgsergio): Think of using openlr::PartnerSegmentId
|
||||
uint32_t m_segmentId = kInvalidSegmentId;
|
||||
|
|
|
@ -48,6 +48,7 @@ DEFINE_string(ids_path, "", "Path to a file with segment ids to process.");
|
|||
DEFINE_string(countries_filename, "",
|
||||
"Name of countries file which describes mwm tree. Used to get country specific "
|
||||
"routing restrictions.");
|
||||
DEFINE_int32(algo_version, 0, "Use new decoding algorithm");
|
||||
|
||||
using namespace openlr;
|
||||
|
||||
|
@ -129,7 +130,7 @@ bool ValidateNumThreads(char const * flagname, int32_t value)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ValidataMwmPath(char const * flagname, std::string const & value)
|
||||
bool ValidateMwmPath(char const * flagname, std::string const & value)
|
||||
{
|
||||
if (value.empty())
|
||||
{
|
||||
|
@ -140,10 +141,28 @@ bool ValidataMwmPath(char const * flagname, std::string const & value)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ValidateVersion(char const * flagname, int32_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
printf("--%s should be specified\n", flagname);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value != 1 && value != 2)
|
||||
{
|
||||
printf("--%s should be one of 1 or 2\n", flagname);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool const g_limitDummy = google::RegisterFlagValidator(&FLAGS_limit, &ValidateLimit);
|
||||
bool const g_numThreadsDummy =
|
||||
google::RegisterFlagValidator(&FLAGS_num_threads, &ValidateNumThreads);
|
||||
bool const g_mwmsPathDummy = google::RegisterFlagValidator(&FLAGS_mwms_path, &ValidataMwmPath);
|
||||
bool const g_mwmsPathDummy = google::RegisterFlagValidator(&FLAGS_mwms_path, &ValidateMwmPath);
|
||||
bool const g_algoVersion = google::RegisterFlagValidator(&FLAGS_algo_version, &ValidateVersion);
|
||||
|
||||
void SaveNonMatchedIds(std::string const & filename, std::vector<DecodedPath> const & paths)
|
||||
{
|
||||
|
@ -257,7 +276,12 @@ int main(int argc, char * argv[])
|
|||
auto const segments = LoadSegments(document);
|
||||
|
||||
std::vector<DecodedPath> paths(segments.size());
|
||||
decoder.Decode(segments, numThreads, paths);
|
||||
switch (FLAGS_algo_version)
|
||||
{
|
||||
case 1: decoder.DecodeV1(segments, numThreads, paths); break;
|
||||
case 2: decoder.DecodeV2(segments, numThreads, paths); break;
|
||||
default: ASSERT(false, ("There should be no way to fall here"));
|
||||
}
|
||||
|
||||
SaveNonMatchedIds(FLAGS_non_matched_ids, paths);
|
||||
if (!FLAGS_assessment_output.empty())
|
||||
|
|
|
@ -66,7 +66,7 @@ bool ValidatePath(Graph::EdgeVector const & path,
|
|||
}
|
||||
} // namespace
|
||||
|
||||
PathsConnector::PathsConnector(double const pathLengthTolerance, Graph const & graph,
|
||||
PathsConnector::PathsConnector(double const pathLengthTolerance, Graph & graph,
|
||||
v2::Stats & stat)
|
||||
: m_pathLengthTolerance(pathLengthTolerance), m_graph(graph), m_stat(stat)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace openlr
|
|||
class PathsConnector
|
||||
{
|
||||
public:
|
||||
PathsConnector(double const pathLengthTolerance, Graph const & graph, v2::Stats & stat);
|
||||
PathsConnector(double const pathLengthTolerance, Graph & graph, v2::Stats & stat);
|
||||
|
||||
bool ConnectCandidates(std::vector<LocationReferencePoint> const & points,
|
||||
std::vector<std::vector<Graph::EdgeVector>> const & lineCandidates,
|
||||
|
@ -29,8 +29,8 @@ private:
|
|||
uint32_t const distanceToNextPoint,
|
||||
Graph::EdgeVector & resultPath);
|
||||
|
||||
double const m_pathLengthTolerance;
|
||||
Graph const & m_graph;
|
||||
double m_pathLengthTolerance;
|
||||
Graph & m_graph;
|
||||
v2::Stats & m_stat;
|
||||
};
|
||||
} // namespace openlr
|
||||
|
|
Loading…
Add table
Reference in a new issue