Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
137
tools/openlr/score_candidate_points_getter.cpp
Normal file
137
tools/openlr/score_candidate_points_getter.cpp
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
#include "openlr/score_candidate_points_getter.hpp"
|
||||
|
||||
#include "openlr/helpers.hpp"
|
||||
|
||||
#include "routing/road_graph.hpp"
|
||||
#include "routing/routing_helpers.hpp"
|
||||
|
||||
#include "storage/country_info_getter.hpp"
|
||||
|
||||
#include "indexer/feature.hpp"
|
||||
#include "indexer/feature_data.hpp"
|
||||
#include "indexer/feature_decl.hpp"
|
||||
#include "indexer/scales.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
#include "geometry/point_with_altitude.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
using namespace routing;
|
||||
|
||||
namespace
|
||||
{
|
||||
// Ends of segments and intermediate points of segments are considered only within this radius.
|
||||
double const kRadius = 30.0;
|
||||
} // namespace
|
||||
|
||||
namespace openlr
|
||||
{
|
||||
void ScoreCandidatePointsGetter::GetJunctionPointCandidates(m2::PointD const & p, bool isLastPoint,
|
||||
ScoreEdgeVec & edgeCandidates)
|
||||
{
|
||||
ScorePointVec pointCandidates;
|
||||
auto const selectCandidates = [&p, &pointCandidates, this](FeatureType & ft)
|
||||
{
|
||||
ft.ParseGeometry(FeatureType::BEST_GEOMETRY);
|
||||
if (ft.GetGeomType() != feature::GeomType::Line || !routing::IsRoad(feature::TypesHolder(ft)))
|
||||
return;
|
||||
|
||||
ft.ForEachPoint([&p, &pointCandidates, this](m2::PointD const & candidate)
|
||||
{
|
||||
if (mercator::DistanceOnEarth(p, candidate) < kRadius)
|
||||
pointCandidates.emplace_back(GetScoreByDistance(p, candidate), candidate);
|
||||
}, scales::GetUpperScale());
|
||||
};
|
||||
|
||||
m_dataSource.ForEachInRect(selectCandidates, mercator::RectByCenterXYAndSizeInMeters(p, kRadius),
|
||||
scales::GetUpperScale());
|
||||
|
||||
base::SortUnique(pointCandidates);
|
||||
std::reverse(pointCandidates.begin(), pointCandidates.end());
|
||||
|
||||
pointCandidates.resize(std::min(m_maxJunctionCandidates, pointCandidates.size()));
|
||||
|
||||
for (auto const & pc : pointCandidates)
|
||||
{
|
||||
Graph::EdgeListT edges;
|
||||
if (!isLastPoint)
|
||||
m_graph.GetOutgoingEdges(geometry::PointWithAltitude(pc.m_point, 0 /* altitude */), edges);
|
||||
else
|
||||
m_graph.GetIngoingEdges(geometry::PointWithAltitude(pc.m_point, 0 /* altitude */), edges);
|
||||
|
||||
for (auto const & e : edges)
|
||||
edgeCandidates.emplace_back(pc.m_score, e);
|
||||
}
|
||||
}
|
||||
|
||||
void ScoreCandidatePointsGetter::EnrichWithProjectionPoints(m2::PointD const & p, ScoreEdgeVec & edgeCandidates)
|
||||
{
|
||||
m_graph.ResetFakes();
|
||||
|
||||
std::vector<std::pair<Graph::Edge, geometry::PointWithAltitude>> vicinities;
|
||||
m_graph.FindClosestEdges(p, static_cast<uint32_t>(m_maxProjectionCandidates), vicinities);
|
||||
for (auto const & v : vicinities)
|
||||
{
|
||||
auto const & edge = v.first;
|
||||
auto const & proj = v.second;
|
||||
|
||||
CHECK(edge.HasRealPart(), ());
|
||||
CHECK(!edge.IsFake(), ());
|
||||
|
||||
if (mercator::DistanceOnEarth(p, proj.GetPoint()) >= kRadius)
|
||||
continue;
|
||||
|
||||
edgeCandidates.emplace_back(GetScoreByDistance(p, proj.GetPoint()), edge);
|
||||
}
|
||||
}
|
||||
|
||||
bool ScoreCandidatePointsGetter::IsJunction(m2::PointD const & p)
|
||||
{
|
||||
Graph::EdgeListT outgoing;
|
||||
m_graph.GetRegularOutgoingEdges(geometry::PointWithAltitude(p, 0 /* altitude */), outgoing);
|
||||
|
||||
Graph::EdgeListT ingoing;
|
||||
m_graph.GetRegularIngoingEdges(geometry::PointWithAltitude(p, 0 /* altitude */), ingoing);
|
||||
|
||||
// Note. At mwm borders the size of |ids| may be bigger than two in case of straight
|
||||
// road because of road feature duplication at borders.
|
||||
std::set<std::pair<uint32_t, uint32_t>> ids;
|
||||
for (auto const & e : outgoing)
|
||||
ids.insert(std::make_pair(e.GetFeatureId().m_index, e.GetSegId()));
|
||||
|
||||
for (auto const & e : ingoing)
|
||||
ids.insert(std::make_pair(e.GetFeatureId().m_index, e.GetSegId()));
|
||||
|
||||
// Size of |ids| is number of different pairs of (feature id, segment id) starting from
|
||||
// |p| plus going to |p|. The size 0, 1 or 2 is considered |p| is not a junction of roads.
|
||||
// If the size is 3 or more it means |p| is an intersection of 3 or more roads.
|
||||
return ids.size() >= 3;
|
||||
}
|
||||
|
||||
Score ScoreCandidatePointsGetter::GetScoreByDistance(m2::PointD const & point, m2::PointD const & candidate)
|
||||
{
|
||||
// Maximum possible score for the distance between an openlr segment ends and an osm segments.
|
||||
Score constexpr kMaxScoreForDist = 70;
|
||||
// If the distance between an openlr segments end and an osm segments end is less or equal
|
||||
// |kMaxScoreDistM| the point gets |kMaxScoreForDist| score.
|
||||
double constexpr kMaxScoreDistM = 5.0;
|
||||
// According to the standard openlr edge should be started from a junction. Despite the fact
|
||||
// that openlr and osm are based on different graphs, the score of junction should be increased.
|
||||
double const junctionFactor = IsJunction(candidate) ? 1.1 : 1.0;
|
||||
|
||||
double const distM = mercator::DistanceOnEarth(point, candidate);
|
||||
double const score = distM <= kMaxScoreDistM
|
||||
? kMaxScoreForDist * junctionFactor
|
||||
: static_cast<double>(kMaxScoreForDist) * junctionFactor / (1.0 + distM - kMaxScoreDistM);
|
||||
|
||||
CHECK_GREATER_OR_EQUAL(score, 0.0, ());
|
||||
CHECK_LESS_OR_EQUAL(score, static_cast<double>(kMaxScoreForDist) * junctionFactor, ());
|
||||
return static_cast<Score>(score);
|
||||
}
|
||||
} // namespace openlr
|
||||
Loading…
Add table
Add a link
Reference in a new issue