intersection classes with variable degree of discretization

This commit is contained in:
Moritz Kobitzsch
2016-05-10 08:37:45 +02:00
committed by Patrick Niklaus
parent 0f3942558f
commit 4d9aa65e78
23 changed files with 724 additions and 702 deletions
+13 -30
View File
@@ -6,6 +6,10 @@
#include <functional>
#include <vector>
#include <boost/functional/hash.hpp>
#include "util/typedefs.hpp"
namespace osrm
{
namespace util
@@ -35,24 +39,8 @@ namespace guidance
class BearingClass
{
public:
using FlagBaseType = std::uint32_t;
const static constexpr double discrete_angle_step_size = 360. / 32;
BearingClass();
// add a continuous angle to the, returns true if no item existed that uses the same discrete
// angle
bool addContinuous(const double bearing);
// add a discrete ID, returns true if no item existed that uses the same discrete angle
bool addDiscreteID(const std::uint8_t id);
//remove a bearing from the list
void resetContinuous(const double bearing);
void resetDiscreteID(const std::uint8_t id);
//is available
bool hasContinuous(const double bearing) const;
bool hasDiscrete(const std::uint8_t id) const;
// Add a bearing to the set
void add(const DiscreteBearing bearing);
// hashing
bool operator==(const BearingClass &other) const;
@@ -60,19 +48,15 @@ class BearingClass
// sorting
bool operator<(const BearingClass &other) const;
std::vector<double> getAvailableBearings() const;
const std::vector<DiscreteBearing> &getAvailableBearings() const;
// get a discrete representation of an angle. Required to map a bearing/angle to the discrete
// ones stored within the class
static std::uint8_t angleToDiscreteID(double angle);
static double discreteIDToAngle( const std::uint8_t );
std::size_t findMatchingBearing(const double bearing) const;
const constexpr static double discrete_step_size = 360. / 24.;
static DiscreteBearing getDiscreteBearing(const double bearing);
// we are hiding the access to the flags behind a protection wall, to make sure the bit logic
// isn't tempered with
private:
// given a list of possible discrete angles, the available angles flag indicates the presence of
// a given turn at the intersection
FlagBaseType available_bearings_mask;
std::vector<DiscreteBearing> available_bearings;
// allow hash access to internal representation
friend std::size_t std::hash<BearingClass>::operator()(const BearingClass &) const;
@@ -88,8 +72,7 @@ namespace std
inline size_t hash<::osrm::util::guidance::BearingClass>::
operator()(const ::osrm::util::guidance::BearingClass &bearing_class) const
{
return hash<::osrm::util::guidance::BearingClass::FlagBaseType>()(
bearing_class.available_bearings_mask);
return boost::hash_value(bearing_class.available_bearings);
}
} // namespace std
+8
View File
@@ -5,6 +5,9 @@
#include <cstdint>
#include <functional>
#include <iostream>
#include <bitset>
namespace osrm
{
namespace util
@@ -51,6 +54,11 @@ class EntryClass
// sorting
bool operator<(const EntryClass &) const;
inline void print() const
{
std::cout << "Flags: " << std::bitset<16>(enabled_entries_flags) << std::endl;
}
private:
// given a list of possible discrete angles, the available angles flag indicates the presence of
// a given turn at the intersection
+24 -60
View File
@@ -3,6 +3,8 @@
/* A set of tools required for guidance in both pre and post-processing */
#include "engine/guidance/route_step.hpp"
#include "engine/phantom_node.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
@@ -47,74 +49,36 @@ inline extractor::guidance::DirectionModifier getTurnDirection(const double angl
return extractor::guidance::DirectionModifier::UTurn;
}
inline double getMatchingDiscreteBearing(const bool requires_entry,
const double bearing,
const EntryClass entry_class,
const std::vector<double> existing_bearings)
inline engine::guidance::Intersection
setIntersectionClasses(engine::guidance::Intersection intersection,
const engine::PhantomNode &phantom)
{
if (existing_bearings.empty())
return 0;
BOOST_ASSERT(intersection.bearing_before == 0 || intersection.bearing_after == 0);
const double bearing = std::max(intersection.bearing_before, intersection.bearing_after);
const double discrete_bearing =
BearingClass::discreteIDToAngle(BearingClass::angleToDiscreteID(bearing));
// it they are very close to the turn, the discrete bearing should be fine
if (std::abs(bearing - discrete_bearing) < 0.25 * BearingClass::discrete_angle_step_size)
intersection.bearing_class = {};
intersection.entry_class = {};
if (bearing >= 180.)
{
const auto isValidEntry = [&]() {
const auto bound = std::upper_bound(existing_bearings.begin(), existing_bearings.end(),
(discrete_bearing - 0.001));
const auto index = bound == existing_bearings.end()
? 0
: std::distance(existing_bearings.begin(), bound);
return entry_class.allowsEntry(index);
};
BOOST_ASSERT(!requires_entry || isValidEntry());
return discrete_bearing;
intersection.bearing_class.add(std::round(bearing - 180.));
if (phantom.forward_segment_id.id != SPECIAL_SEGMENTID &&
phantom.reverse_segment_id.id != SPECIAL_SEGMENTID)
intersection.entry_class.activate(0);
intersection.bearing_class.add(std::round(bearing));
intersection.entry_class.activate(1);
}
else
{
// the next larger bearing or first if we are wrapping around at zero
const auto next_index =
std::distance(existing_bearings.begin(),
std::lower_bound(existing_bearings.begin(), existing_bearings.end(),
discrete_bearing)) %
existing_bearings.size();
// next smaller bearing or last if we are wrapping around at zero
const auto previous_index =
(next_index + existing_bearings.size() - 1) % existing_bearings.size();
const auto difference = [](const double first, const double second) {
return std::min(std::abs(first - second), 360.0 - std::abs(first - second));
};
const auto next_bearing = existing_bearings[next_index];
const auto previous_bearing = existing_bearings[previous_index];
const auto decideOnBearing = [&](
const std::size_t preferred_index, const double preferred_bearing,
const std::size_t alternative_index, const double alternative_bearing) {
if (!requires_entry || entry_class.allowsEntry(preferred_index))
return preferred_bearing;
else if (entry_class.allowsEntry(alternative_index))
return alternative_bearing;
else
{
SimpleLogger().Write(logDEBUG)
<< "Cannot find a valid entry for a discrete Bearing in Turn Classificiation";
return 0.;
}
};
if (difference(bearing, next_bearing) < difference(bearing, previous_index))
return decideOnBearing(next_index, next_bearing, previous_index, previous_bearing);
else
return decideOnBearing(previous_index, previous_bearing, next_index, next_bearing);
intersection.bearing_class.add(std::round(bearing));
intersection.entry_class.activate(0);
intersection.bearing_class.add(std::round(bearing + 180.));
if (phantom.forward_segment_id.id != SPECIAL_SEGMENTID &&
phantom.reverse_segment_id.id != SPECIAL_SEGMENTID)
intersection.entry_class.activate(1);
}
return 0;
return intersection;
}
} // namespace guidance
} // namespace util
} // namespace osrm