Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
193
libs/routing/road_access.cpp
Normal file
193
libs/routing/road_access.cpp
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
#include "routing/road_access.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <sstream>
|
||||
|
||||
namespace routing
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string const kNames[] = {"No", "Private", "Destination", "Yes", "Count"};
|
||||
|
||||
template <typename KV>
|
||||
std::string DebugPrintKV(KV const & kvs, size_t maxKVToShow)
|
||||
{
|
||||
// Print all range for now.
|
||||
return DebugPrintSequence(kvs.begin(), kvs.end());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/** RoadAccess --------------------------------------------------------------------------------------
|
||||
* @todo (bykoinako) It's a fast fix for release. The idea behind it is to remember the time of
|
||||
* creation RoadAccess instance and return it instead of getting time when m_currentTimeGetter() is
|
||||
* called. But it's not understandable now why m_currentTimeGetter() is called when
|
||||
* cross_mwm section is built.
|
||||
*
|
||||
* @todo (vng) Return back lazy time calculation.
|
||||
* It's called in cross_mwm_section via IndexGraph::CalculateEdgeWeight.
|
||||
* Fixed by setting custom time getter in BuildRoutingCrossMwmSection -> FillWeights.
|
||||
*/
|
||||
RoadAccess::RoadAccess() : m_currentTimeGetter([]() { return GetCurrentTimestamp(); }) {}
|
||||
|
||||
std::pair<RoadAccess::Type, RoadAccess::Confidence> RoadAccess::GetAccess(uint32_t featureId,
|
||||
RouteWeight const & weightToFeature) const
|
||||
{
|
||||
return GetAccess(featureId, weightToFeature.GetWeight());
|
||||
}
|
||||
|
||||
std::pair<RoadAccess::Type, RoadAccess::Confidence> RoadAccess::GetAccess(RoadPoint const & point,
|
||||
RouteWeight const & weightToPoint) const
|
||||
{
|
||||
return GetAccess(point, weightToPoint.GetWeight());
|
||||
}
|
||||
|
||||
std::pair<RoadAccess::Type, RoadAccess::Confidence> RoadAccess::GetAccess(uint32_t featureId, double weight) const
|
||||
{
|
||||
auto const itConditional = m_wayToAccessConditional.find(featureId);
|
||||
if (itConditional != m_wayToAccessConditional.cend())
|
||||
{
|
||||
auto const time = m_currentTimeGetter();
|
||||
auto const & conditional = itConditional->second;
|
||||
for (auto const & access : conditional.GetAccesses())
|
||||
{
|
||||
auto const op = GetConfidenceForAccessConditional(time + weight, access.m_openingHours);
|
||||
if (op)
|
||||
return {access.m_type, *op};
|
||||
}
|
||||
}
|
||||
|
||||
return GetAccessWithoutConditional(featureId);
|
||||
}
|
||||
|
||||
std::pair<RoadAccess::Type, RoadAccess::Confidence> RoadAccess::GetAccess(RoadPoint const & point, double weight) const
|
||||
{
|
||||
auto const itConditional = m_pointToAccessConditional.find(point);
|
||||
if (itConditional != m_pointToAccessConditional.cend())
|
||||
{
|
||||
auto const time = m_currentTimeGetter();
|
||||
auto const & conditional = itConditional->second;
|
||||
for (auto const & access : conditional.GetAccesses())
|
||||
{
|
||||
auto const op = GetConfidenceForAccessConditional(time + weight, access.m_openingHours);
|
||||
if (op)
|
||||
return {access.m_type, *op};
|
||||
}
|
||||
}
|
||||
|
||||
return GetAccessWithoutConditional(point);
|
||||
}
|
||||
|
||||
std::pair<RoadAccess::Type, RoadAccess::Confidence> RoadAccess::GetAccessWithoutConditional(uint32_t featureId) const
|
||||
{
|
||||
// todo(@m) This may or may not be too slow. Consider profiling this and using
|
||||
// a Bloom filter or anything else that is faster than ska::flat_hash_map
|
||||
auto const it = m_wayToAccess.find(featureId);
|
||||
if (it != m_wayToAccess.cend())
|
||||
return {it->second, Confidence::Sure};
|
||||
|
||||
return {Type::Yes, Confidence::Sure};
|
||||
}
|
||||
|
||||
std::pair<RoadAccess::Type, RoadAccess::Confidence> RoadAccess::GetAccessWithoutConditional(
|
||||
RoadPoint const & point) const
|
||||
{
|
||||
auto const it = m_pointToAccess.find(point);
|
||||
if (it != m_pointToAccess.cend())
|
||||
return {it->second, Confidence::Sure};
|
||||
|
||||
return {Type::Yes, Confidence::Sure};
|
||||
}
|
||||
|
||||
bool RoadAccess::operator==(RoadAccess const & rhs) const
|
||||
{
|
||||
return m_wayToAccess == rhs.m_wayToAccess && m_pointToAccess == rhs.m_pointToAccess &&
|
||||
m_wayToAccessConditional == rhs.m_wayToAccessConditional &&
|
||||
m_pointToAccessConditional == rhs.m_pointToAccessConditional;
|
||||
}
|
||||
|
||||
// static
|
||||
std::optional<RoadAccess::Confidence> RoadAccess::GetConfidenceForAccessConditional(
|
||||
time_t momentInTime, osmoh::OpeningHours const & openingHours)
|
||||
{
|
||||
auto const left = momentInTime - kConfidenceIntervalSeconds / 2;
|
||||
auto const right = momentInTime + kConfidenceIntervalSeconds / 2;
|
||||
|
||||
auto const leftOpen = openingHours.IsOpen(left);
|
||||
auto const rightOpen = openingHours.IsOpen(right);
|
||||
|
||||
if (!leftOpen && !rightOpen)
|
||||
return {};
|
||||
|
||||
return leftOpen && rightOpen ? Confidence::Sure : Confidence::Maybe;
|
||||
}
|
||||
|
||||
// Functions ---------------------------------------------------------------------------------------
|
||||
time_t GetCurrentTimestamp()
|
||||
{
|
||||
using system_clock = std::chrono::system_clock;
|
||||
return system_clock::to_time_t(system_clock::now());
|
||||
}
|
||||
|
||||
std::string ToString(RoadAccess::Type type)
|
||||
{
|
||||
if (type <= RoadAccess::Type::Count)
|
||||
return kNames[static_cast<size_t>(type)];
|
||||
CHECK(false, ("Bad road access type", static_cast<size_t>(type)));
|
||||
return {};
|
||||
}
|
||||
|
||||
void FromString(std::string_view s, RoadAccess::Type & result)
|
||||
{
|
||||
for (size_t i = 0; i <= static_cast<size_t>(RoadAccess::Type::Count); ++i)
|
||||
{
|
||||
if (s == kNames[i])
|
||||
{
|
||||
result = static_cast<RoadAccess::Type>(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
CHECK(false, ("Could not read RoadAccess from the string", s));
|
||||
}
|
||||
|
||||
std::string DebugPrint(RoadAccess::Conditional const & conditional)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Conditional { ";
|
||||
for (auto const & access : conditional.GetAccesses())
|
||||
oss << DebugPrint(access.m_type) << " @ (" << access.m_openingHours.GetRule() << "), ";
|
||||
oss << " }";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string DebugPrint(RoadAccess::Confidence confidence)
|
||||
{
|
||||
switch (confidence)
|
||||
{
|
||||
case RoadAccess::Confidence::Maybe: return "Maybe";
|
||||
case RoadAccess::Confidence::Sure: return "Sure";
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
std::string DebugPrint(RoadAccess::Type type)
|
||||
{
|
||||
return ToString(type);
|
||||
}
|
||||
|
||||
std::string DebugPrint(RoadAccess const & r)
|
||||
{
|
||||
size_t constexpr kMaxIdsToShow = 10;
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "RoadAccess { WayToAccess " << DebugPrintKV(r.GetWayToAccess(), kMaxIdsToShow) << "; PointToAccess "
|
||||
<< DebugPrintKV(r.GetPointToAccess(), kMaxIdsToShow) << "; WayToAccessConditional "
|
||||
<< DebugPrintKV(r.GetWayToAccessConditional(), kMaxIdsToShow) << "; PointToAccessConditional "
|
||||
<< DebugPrintKV(r.GetPointToAccessConditional(), kMaxIdsToShow) << " }";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace routing
|
||||
Loading…
Add table
Add a link
Reference in a new issue