2016-08-17 03:49:19 -04:00
|
|
|
#ifndef OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
|
|
|
|
#define OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
|
|
|
|
|
2016-11-15 05:21:26 -05:00
|
|
|
#include <utility>
|
2016-08-17 03:49:19 -04:00
|
|
|
#include <vector>
|
|
|
|
|
2016-11-03 11:14:04 -04:00
|
|
|
#include "extractor/compressed_edge_container.hpp"
|
2016-08-17 03:49:19 -04:00
|
|
|
#include "extractor/query_node.hpp"
|
2016-11-03 11:14:04 -04:00
|
|
|
|
|
|
|
#include "util/attributes.hpp"
|
2016-08-17 03:49:19 -04:00
|
|
|
#include "util/coordinate.hpp"
|
|
|
|
#include "util/node_based_graph.hpp"
|
|
|
|
|
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace extractor
|
|
|
|
{
|
|
|
|
namespace guidance
|
|
|
|
{
|
|
|
|
|
|
|
|
class CoordinateExtractor
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CoordinateExtractor(const util::NodeBasedDynamicGraph &node_based_graph,
|
|
|
|
const extractor::CompressedEdgeContainer &compressed_geometries,
|
|
|
|
const std::vector<extractor::QueryNode> &node_coordinates);
|
|
|
|
|
|
|
|
/* Find a interpolated coordinate a long the compressed geometries. The desired coordinate
|
|
|
|
* should be in a certain distance. This method is dedicated to find representative coordinates
|
|
|
|
* at turns.
|
2017-01-06 20:10:02 -05:00
|
|
|
* Note: The segment between intersection and turn coordinate can be zero, if the OSM modelling
|
|
|
|
* is unfortunate. See https://github.com/Project-OSRM/osrm-backend/issues/3470
|
2016-08-17 03:49:19 -04:00
|
|
|
*/
|
2016-11-03 11:14:04 -04:00
|
|
|
OSRM_ATTR_WARN_UNUSED
|
2016-08-17 03:49:19 -04:00
|
|
|
util::Coordinate GetCoordinateAlongRoad(const NodeID intersection_node,
|
|
|
|
const EdgeID turn_edge,
|
|
|
|
const bool traversed_in_reverse,
|
|
|
|
const NodeID to_node,
|
|
|
|
const std::uint8_t number_of_in_lanes) const;
|
|
|
|
|
2016-11-18 03:38:26 -05:00
|
|
|
// Given a set of precomputed coordinates, select the representative coordinate along the road
|
|
|
|
// that best describes the turn
|
2016-11-03 11:14:04 -04:00
|
|
|
OSRM_ATTR_WARN_UNUSED
|
2016-11-15 05:21:26 -05:00
|
|
|
util::Coordinate
|
|
|
|
ExtractRepresentativeCoordinate(const NodeID intersection_node,
|
|
|
|
const EdgeID turn_edge,
|
|
|
|
const bool traversed_in_reverse,
|
|
|
|
const NodeID to_node,
|
|
|
|
const std::uint8_t intersection_lanes,
|
|
|
|
std::vector<util::Coordinate> coordinates) const;
|
|
|
|
|
|
|
|
// instead of finding only a single coordinate, we can also list all coordinates along a
|
|
|
|
// road.
|
|
|
|
OSRM_ATTR_WARN_UNUSED std::vector<util::Coordinate>
|
|
|
|
GetCoordinatesAlongRoad(const NodeID intersection_node,
|
|
|
|
const EdgeID turn_edge,
|
|
|
|
const bool traversed_in_reverse,
|
|
|
|
const NodeID to_node) const;
|
2016-08-17 03:49:19 -04:00
|
|
|
|
2016-10-20 06:15:36 -04:00
|
|
|
// wrapper in case of normal forward edges (traversed_in_reverse = false, to_node =
|
|
|
|
// node_based_graph.GetTarget(turn_edge)
|
2016-11-03 11:14:04 -04:00
|
|
|
OSRM_ATTR_WARN_UNUSED
|
2016-10-20 06:15:36 -04:00
|
|
|
std::vector<util::Coordinate> GetForwardCoordinatesAlongRoad(const NodeID from,
|
|
|
|
const EdgeID turn_edge) const;
|
|
|
|
|
2016-11-10 10:05:24 -05:00
|
|
|
// a less precise way to compute coordinates along a route. Due to the heavy interaction of
|
|
|
|
// graph traversal and turn instructions, we often don't care for high precision. We only want
|
|
|
|
// to check for available connections in order, or find (with room for error) the straightmost
|
|
|
|
// turn. This function will offer a bit more error potential but allow for much higher
|
|
|
|
// performance
|
|
|
|
OSRM_ATTR_WARN_UNUSED
|
|
|
|
util::Coordinate GetCoordinateCloseToTurn(const NodeID from_node,
|
|
|
|
const EdgeID turn_edge,
|
|
|
|
const bool traversed_in_reverse,
|
|
|
|
const NodeID to_node) const;
|
|
|
|
|
2016-08-17 03:49:19 -04:00
|
|
|
/* When extracting the coordinates, we first extract all coordinates. We don't care about most
|
|
|
|
* of them, though.
|
|
|
|
*
|
|
|
|
* Our very first step trims the coordinates to a saller set, close to the intersection.. The
|
|
|
|
* idea here is to filter all coordinates at the end of the road and consider only the formi
|
|
|
|
* close to the intersection:
|
|
|
|
*
|
|
|
|
* a -------------- v ----------.
|
|
|
|
* .
|
|
|
|
* .
|
|
|
|
* .
|
|
|
|
* b
|
|
|
|
*
|
|
|
|
* For calculating the turn angle for the intersection at `a`, we do not care about the turn
|
|
|
|
* between `v` and `b`. This calculation trims the coordinates to the ones immediately at the
|
|
|
|
* intersection.
|
2016-11-03 11:14:04 -04:00
|
|
|
*
|
|
|
|
* The optional length cache needs to store the accumulated distance up to the respective
|
|
|
|
* coordinate index [0,d(0,1),...]
|
2016-08-17 03:49:19 -04:00
|
|
|
*/
|
2016-11-03 11:14:04 -04:00
|
|
|
OSRM_ATTR_WARN_UNUSED
|
|
|
|
std::vector<util::Coordinate>
|
|
|
|
TrimCoordinatesToLength(std::vector<util::Coordinate> coordinates,
|
|
|
|
const double desired_length,
|
|
|
|
const std::vector<double> &length_cache = {}) const;
|
|
|
|
|
|
|
|
OSRM_ATTR_WARN_UNUSED
|
|
|
|
std::vector<double> PrepareLengthCache(const std::vector<util::Coordinate> &coordinates,
|
|
|
|
const double limit) const;
|
2016-08-17 03:49:19 -04:00
|
|
|
|
|
|
|
/* when looking at a set of coordinates, this function allows trimming the vector to a smaller,
|
|
|
|
* only containing coordinates up to a given distance along the path. The last coordinate might
|
|
|
|
* be interpolated
|
|
|
|
*/
|
2016-11-03 11:14:04 -04:00
|
|
|
OSRM_ATTR_WARN_UNUSED
|
2016-08-17 03:49:19 -04:00
|
|
|
std::vector<util::Coordinate>
|
|
|
|
TrimCoordinatesByLengthFront(std::vector<util::Coordinate> coordinates,
|
|
|
|
const double desired_length) const;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* to correct for the initial offset, we move the lookahead coordinate close
|
|
|
|
* to the original road. We do so by subtracting the difference between the
|
|
|
|
* turn coordinate and the offset coordinate from the lookahead coordinge:
|
|
|
|
*
|
|
|
|
* a ------ b ------ c
|
|
|
|
* |
|
|
|
|
* d
|
|
|
|
* \
|
|
|
|
* \
|
|
|
|
* e
|
|
|
|
*
|
|
|
|
* is converted to:
|
|
|
|
*
|
|
|
|
* a ------ b ------ c
|
|
|
|
* \
|
|
|
|
* \
|
|
|
|
* e
|
|
|
|
*
|
|
|
|
* for fixpoint `b`, vector_base `d` and vector_head `e`
|
|
|
|
*/
|
2016-11-03 11:14:04 -04:00
|
|
|
OSRM_ATTR_WARN_UNUSED
|
2016-08-17 03:49:19 -04:00
|
|
|
util::Coordinate GetCorrectedCoordinate(const util::Coordinate fixpoint,
|
|
|
|
const util::Coordinate vector_base,
|
|
|
|
const util::Coordinate vector_head) const;
|
|
|
|
|
|
|
|
/* generate a uniform vector of coordinates in same range distances
|
|
|
|
*
|
|
|
|
* Turns:
|
|
|
|
* x ------------ x -- x - x
|
|
|
|
*
|
|
|
|
* Into:
|
|
|
|
* x -- x -- x -- x -- x - x
|
|
|
|
*/
|
2016-11-03 11:14:04 -04:00
|
|
|
OSRM_ATTR_WARN_UNUSED
|
2016-08-17 03:49:19 -04:00
|
|
|
std::vector<util::Coordinate>
|
|
|
|
SampleCoordinates(const std::vector<util::Coordinate> &coordinates,
|
|
|
|
const double length,
|
|
|
|
const double rate) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
const util::NodeBasedDynamicGraph &node_based_graph;
|
|
|
|
const extractor::CompressedEdgeContainer &compressed_geometries;
|
|
|
|
const std::vector<extractor::QueryNode> &node_coordinates;
|
|
|
|
|
|
|
|
double ComputeInterpolationFactor(const double desired_distance,
|
|
|
|
const double distance_to_first,
|
|
|
|
const double distance_to_second) const;
|
|
|
|
|
|
|
|
std::pair<util::Coordinate, util::Coordinate>
|
|
|
|
RegressionLine(const std::vector<util::Coordinate> &coordinates) const;
|
|
|
|
|
|
|
|
/* In an ideal world, the road would only have two coordinates if it goes mainly straigt. Since
|
|
|
|
* OSM is operating on noisy data, we have some variations going straight.
|
|
|
|
*
|
|
|
|
* b d
|
|
|
|
* a ---------------------------------------------- e
|
|
|
|
* c
|
|
|
|
*
|
|
|
|
* The road from a-e offers a lot of variation, even though it is mostly straight. Here we
|
|
|
|
* calculate the distances of all nodes in between to the straight line between a and e. If the
|
|
|
|
* distances inbetween are small, we assume a straight road. To calculate these distances, we
|
|
|
|
* don't use the coordinates of the road itself but our just calculated regression vector
|
|
|
|
*/
|
|
|
|
double GetMaxDeviation(std::vector<util::Coordinate>::const_iterator range_begin,
|
|
|
|
const std::vector<util::Coordinate>::const_iterator &range_end,
|
|
|
|
const util::Coordinate straight_begin,
|
|
|
|
const util::Coordinate straight_end) const;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* the curve is still best described as looking at the very first vector for the turn angle.
|
|
|
|
* Consider:
|
|
|
|
*
|
|
|
|
* |
|
|
|
|
* a - 1
|
|
|
|
* | o
|
|
|
|
* | 2
|
|
|
|
* | o
|
|
|
|
* | 3
|
|
|
|
* | o
|
|
|
|
* | 4
|
|
|
|
*
|
|
|
|
* The turn itself from a-1 would be considered as a 90 degree turn, even though the road is
|
|
|
|
* taking a turn later.
|
|
|
|
* In this situaiton we return the very first coordinate, describing the road just at the
|
|
|
|
* turn.
|
|
|
|
* As an added benefit, we get a straight turn at a curved road:
|
|
|
|
*
|
|
|
|
* o b o
|
|
|
|
* o o
|
|
|
|
* o o
|
|
|
|
* o o
|
|
|
|
* o o
|
|
|
|
* a c
|
|
|
|
*
|
|
|
|
* The turn from a-b to b-c is straight. With every vector we go further down the road, the
|
|
|
|
* turn
|
|
|
|
* angle would get stronger. Therefore we consider the very first coordinate as our best
|
|
|
|
* choice
|
|
|
|
*/
|
|
|
|
bool IsCurve(const std::vector<util::Coordinate> &coordinates,
|
|
|
|
const std::vector<double> &segment_distances,
|
|
|
|
const double segment_length,
|
|
|
|
const double considered_lane_width,
|
|
|
|
const util::NodeBasedEdgeData &edge_data) const;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the very first coordinate is within lane offsets and the rest offers a near straight line,
|
|
|
|
* we use an offset coordinate.
|
|
|
|
*
|
|
|
|
* ----------------------------------------
|
|
|
|
*
|
|
|
|
* ----------------------------------------
|
|
|
|
* a -
|
|
|
|
* ----------------------------------------
|
|
|
|
* \
|
|
|
|
* ----------------------------------------
|
|
|
|
* \
|
|
|
|
* b --------------------c
|
|
|
|
*
|
|
|
|
* Will be considered a very slight turn, instead of the near 90 degree turn we see right here.
|
|
|
|
*/
|
|
|
|
bool IsDirectOffset(const std::vector<util::Coordinate> &coordinates,
|
|
|
|
const std::size_t straight_index,
|
|
|
|
const double straight_distance,
|
|
|
|
const double segment_length,
|
|
|
|
const std::vector<double> &segment_distances,
|
|
|
|
const std::uint8_t considered_lanes) const;
|
2016-11-18 03:38:26 -05:00
|
|
|
|
|
|
|
// find the coordinate at a specific location in the vector
|
|
|
|
util::Coordinate ExtractCoordinateAtLength(const double distance,
|
|
|
|
const std::vector<util::Coordinate> &coordinates,
|
|
|
|
const std::vector<double> &length_cache) const;
|
|
|
|
util::Coordinate
|
|
|
|
ExtractCoordinateAtLength(const double distance,
|
|
|
|
const std::vector<util::Coordinate> &coordinates) const;
|
2016-08-17 03:49:19 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace guidance
|
|
|
|
} // namespace extractor
|
|
|
|
} // namespace osrm
|
|
|
|
|
|
|
|
#endif // OSRM_EXTRACTOR_COORDINATE_EXTRACTOR_HPP_
|