diff --git a/docs/http.md b/docs/http.md index e2bcd0141d7..c9dbb2f0ef2 100644 --- a/docs/http.md +++ b/docs/http.md @@ -551,6 +551,7 @@ Vector tiles contain two layers: | `weight ` | `integer` | how long this segment takes to traverse, in units (may differ from `duration` when artificial biasing is applied in the Lua profiles). ACTUAL ROUTING USES THIS VALUE. | | `name` | `string` | the name of the road this segment belongs to | | `rate` | `float` | the value of `length/weight` - analagous to `speed`, but using the `weight` value rather than `duration`, rounded to the nearest integer | +| `is_startpoint` | `boolean` | whether this segment can be used as a start/endpoint for routes | `turns` layer: diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index 76b38f4a9f0..7aabc704ed9 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -313,7 +313,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const float max_distance, const Approach approach, - const bool use_all_edges = false) const override final + const bool use_all_edges) const override final { BOOST_ASSERT(m_geospatial_query.get()); @@ -327,7 +327,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade const int bearing, const int bearing_range, const Approach approach, - const bool use_all_edges = false) const override final + const bool use_all_edges) const override final { BOOST_ASSERT(m_geospatial_query.get()); diff --git a/include/engine/geospatial_query.hpp b/include/engine/geospatial_query.hpp index d663849accc..42f8105b887 100644 --- a/include/engine/geospatial_query.hpp +++ b/include/engine/geospatial_query.hpp @@ -27,12 +27,6 @@ inline std::pair boolPairAnd(const std::pair &A, { return std::make_pair(A.first && B.first, A.second && B.second); } -inline std::pair boolPairAnd(const std::pair &A, - const std::pair &B, - const std::pair &C) -{ - return std::make_pair(A.first && B.first && C.first, A.second && B.second && C.second); -} // Implements complex queries on top of an RTree and builds PhantomNodes from it. // @@ -60,14 +54,14 @@ template class GeospatialQuery NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const double max_distance, const Approach approach, - const bool use_all_edges = false) const + const bool use_all_edges) const { auto results = rtree.Nearest( input_coordinate, [this, approach, &input_coordinate, use_all_edges](const CandidateSegment &segment) { - return boolPairAnd(boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment)), - boolPairAnd(CheckSnappable(segment, use_all_edges), - CheckApproach(input_coordinate, segment, approach))); + return boolPairAnd( + boolPairAnd(HasValidEdge(segment, use_all_edges), CheckSegmentExclude(segment)), + CheckApproach(input_coordinate, segment, approach)); }, [this, max_distance, input_coordinate](const std::size_t, const CandidateSegment &segment) { @@ -85,16 +79,16 @@ template class GeospatialQuery const int bearing, const int bearing_range, const Approach approach, - const bool use_all_edges = false) const + const bool use_all_edges) const { auto results = rtree.Nearest( input_coordinate, [this, approach, &input_coordinate, bearing, bearing_range, use_all_edges]( const CandidateSegment &segment) { auto use_direction = - boolPairAnd(boolPairAnd(CheckSnappable(segment, use_all_edges), - CheckSegmentBearing(segment, bearing, bearing_range)), - boolPairAnd(HasValidEdge(segment), CheckSegmentExclude(segment))); + boolPairAnd(CheckSegmentBearing(segment, bearing, bearing_range), + boolPairAnd(HasValidEdge(segment, use_all_edges), + CheckSegmentExclude(segment))); use_direction = boolPairAnd(use_direction, CheckApproach(input_coordinate, segment, approach)); return use_direction; @@ -632,25 +626,14 @@ template class GeospatialQuery return std::make_pair(forward_bearing_valid, backward_bearing_valid); } - std::pair CheckSnappable(const CandidateSegment &segment, - const bool use_all_edges) const - { - - const bool forward_segment_snappable = segment.data.forward_segment_id.enabled && - (segment.data.is_startpoint || use_all_edges); - const bool reverse_segment_snappable = segment.data.reverse_segment_id.enabled && - (segment.data.is_startpoint || use_all_edges); - - return std::make_pair(forward_segment_snappable, reverse_segment_snappable); - } - /** * Checks to see if the edge weights are valid. We might have an edge, * but a traffic update might set the speed to 0 (weight == INVALID_SEGMENT_WEIGHT). * which means that this edge is not currently traversible. If this is the case, * then we shouldn't snap to this edge. */ - std::pair HasValidEdge(const CandidateSegment &segment) const + std::pair HasValidEdge(const CandidateSegment &segment, + const bool use_all_edges = false) const { bool forward_edge_valid = false; @@ -674,6 +657,9 @@ template class GeospatialQuery reverse_edge_valid = data.reverse_segment_id.enabled; } + forward_edge_valid = forward_edge_valid && (data.is_startpoint || use_all_edges); + reverse_edge_valid = reverse_edge_valid && (data.is_startpoint || use_all_edges); + return std::make_pair(forward_edge_valid, reverse_edge_valid); } diff --git a/src/engine/plugins/tile.cpp b/src/engine/plugins/tile.cpp index bd776756640..4ad1e6e2297 100644 --- a/src/engine/plugins/tile.cpp +++ b/src/engine/plugins/tile.cpp @@ -294,6 +294,7 @@ struct SpeedLayer : public vtzero::layer_builder vtzero::index_value key_duration; vtzero::index_value key_name; vtzero::index_value key_rate; + vtzero::index_value key_is_startpoint; SpeedLayer(vtzero::tile_builder &tile) : layer_builder(tile, "speeds"), uint_index(*this), double_index(*this), @@ -302,7 +303,8 @@ struct SpeedLayer : public vtzero::layer_builder key_datasource(add_key_without_dup_check("datasource")), key_weight(add_key_without_dup_check("weight")), key_duration(add_key_without_dup_check("duration")), - key_name(add_key_without_dup_check("name")), key_rate(add_key_without_dup_check("rate")) + key_name(add_key_without_dup_check("name")), key_rate(add_key_without_dup_check("rate")), + key_is_startpoint(add_key_without_dup_check("is_startpoint")) { } @@ -349,6 +351,11 @@ class SpeedLayerFeatureBuilder : public vtzero::linestring_feature_builder void set_rate(double value) { add_property(m_layer.key_rate, m_layer.double_index(value)); } + void set_is_startpoint(bool value) + { + add_property(m_layer.key_is_startpoint, m_layer.bool_index(value)); + } + }; // class SpeedLayerFeatureBuilder struct TurnsLayer : public vtzero::layer_builder @@ -485,6 +492,8 @@ void encodeVectorTile(const DataFacadeBase &facade, const auto reverse_datasource_idx = reverse_datasource_range( reverse_datasource_range.size() - edge.fwd_segment_position - 1); + const auto is_startpoint = edge.is_startpoint; + const auto component_id = facade.GetComponentID(edge.forward_segment_id.id); const auto name_id = facade.GetNameIndex(edge.forward_segment_id.id); auto name = facade.GetNameForID(name_id); @@ -516,6 +525,7 @@ void encodeVectorTile(const DataFacadeBase &facade, fbuilder.set_duration(forward_duration / 10.0); fbuilder.set_name(name); fbuilder.set_rate(forward_rate / 10.0); + fbuilder.set_is_startpoint(is_startpoint); fbuilder.commit(); }