Compare commits

...

13 Commits

Author SHA1 Message Date
Siarhei Fedartsou c87ed8ebc0 Merge with master 2024-05-21 19:39:30 +02:00
Siarhei Fedartsou f19d64970a Merge branch 'master' into pr-6611 2024-05-21 19:35:50 +02:00
Siarhei Fedartsou d259848456 Optimise R-tree queries in the case of map matching (#6881) 2024-05-20 12:32:40 +02:00
Siarhei Fedartsou 8a82d3929c Improve map matching benchmark (#6885) 2024-05-20 11:15:55 +02:00
Siarhei Fedartsou 89fce286a7 Fix benchmark script for the case if PR has empty description (#6887) 2024-05-20 09:16:53 +02:00
Siarhei Fedartsou 11c7ddc84d Fix failing gcc-13 based CI jobs (#6886)
* Attempt to fix failing CI on gcc-13 jobs

* Attempt to fix failing CI on gcc-13 jobs

* Attempt to fix failing CI on gcc-13 jobs

* Attempt to fix failing CI on gcc-13 jobs

* Attempt to fix failing CI on gcc-13 jobs
2024-05-19 19:30:24 +02:00
Siarhei Fedartsou 54e50a67a8 Add benchmarks comparison job (#6880) 2024-05-14 17:14:59 +02:00
Bart Louwers c00c157479 Replace dead link with archive.org link (#6882) 2024-05-14 11:49:49 +02:00
Dennis Luxen 56d2d4dacd Merge branch 'master' into boost_optional_merge 2024-05-06 17:39:54 +02:00
Mugr Rex 1107a14a2c Removed nodejs
Seems like my local build is ok, but in CI
the references to engine are still there
so I am reverting code in /nodejs to master
2023-04-24 19:16:27 +02:00
Mugr Rex 5b23b11129 Readded updater
Must have been lost while concating everything into one commit
2023-04-24 19:10:04 +02:00
Mugr Rex 23fb96c4f2 Fixed error in /nodejs 2023-04-21 13:16:14 +02:00
Mugr Rex 45bfe937aa Final merge commit 2023-04-20 16:04:04 +02:00
40 changed files with 2374 additions and 251 deletions
+67 -18
View File
@@ -151,7 +151,7 @@ jobs:
- name: gcc-13-debug-cov
continue-on-error: false
node: 20
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
BUILD_TOOLS: ON
BUILD_TYPE: Debug
CCOMPILER: gcc-13
@@ -248,12 +248,11 @@ jobs:
- name: gcc-13-release
continue-on-error: false
node: 20
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
BUILD_TOOLS: ON
BUILD_TYPE: Release
CCOMPILER: gcc-13
CXXCOMPILER: g++-13
ENABLE_BENCHMARKS: ON
CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
- name: gcc-12-release
@@ -264,7 +263,6 @@ jobs:
BUILD_TYPE: Release
CCOMPILER: gcc-12
CXXCOMPILER: g++-12
ENABLE_BENCHMARKS: ON
CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
- name: gcc-11-release
@@ -275,7 +273,6 @@ jobs:
BUILD_TYPE: Release
CCOMPILER: gcc-11
CXXCOMPILER: g++-11
ENABLE_BENCHMARKS: ON
- name: conan-linux-release-node
build_node_package: true
@@ -511,18 +508,6 @@ jobs:
fi
popd
npm test
- name: Run benchmarks
if: ${{ matrix.ENABLE_BENCHMARKS == 'ON' }}
run: |
pushd ${OSRM_BUILD_DIR}
make --jobs=${JOBS} benchmarks
./src/benchmarks/alias-bench
./src/benchmarks/json-render-bench ../src/benchmarks/portugal_to_korea.json
./src/benchmarks/match-bench ../test/data/ch/monaco.osrm ch
./src/benchmarks/match-bench ../test/data/mld/monaco.osrm mld
./src/benchmarks/packedvector-bench
./src/benchmarks/rtree-bench ../test/data/monaco.osrm.ramIndex ../test/data/monaco.osrm.fileIndex ../test/data/monaco.osrm.nbg_nodes
popd
- name: Use Node 18
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
@@ -595,8 +580,72 @@ jobs:
replacesArtifacts: true
token: ${{ secrets.GITHUB_TOKEN }}
benchmarks:
if: github.event_name == 'pull_request'
needs: [format-taginfo-docs]
runs-on: ubuntu-22.04
env:
CCOMPILER: clang-13
CXXCOMPILER: clang++-13
CC: clang-13
CXX: clang++-13
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
GITHUB_REPOSITORY: ${{ github.repository }}
steps:
- name: Enable compiler cache
uses: actions/cache@v3
with:
path: ~/.ccache
key: v1-ccache-benchmarks-${{ github.sha }}
restore-keys: |
v1-ccache-benchmarks-
- name: Enable Conan cache
uses: actions/cache@v3
with:
path: ~/.conan
key: v1-conan-benchmarks-${{ github.sha }}
restore-keys: |
v1-conan-benchmarks-
- name: Checkout PR Branch
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }}
path: pr
- run: python3 -m pip install "conan<2.0.0" "requests==2.31.0"
- name: Build PR Branch
run: |
mkdir -p pr/build
cd pr/build
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
make -j$(nproc) benchmarks
cd ..
make -C test/data
- name: Checkout Base Branch
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.base.ref }}
path: base
- name: Build Base Branch
run: |
mkdir base/build
cd base/build
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
make -j$(nproc) benchmarks
cd ..
make -C test/data
- name: Run Benchmarks
run: |
./pr/scripts/ci/run_benchmarks.sh base pr
- name: Post Benchmark Results
run: |
python3 pr/scripts/ci/post_benchmark_results.py base_results pr_results
ci-complete:
runs-on: ubuntu-22.04
needs: [build-test-publish, docker-image, windows-release-node]
needs: [build-test-publish, docker-image, windows-release-node, benchmarks]
steps:
- run: echo "CI complete"
+2
View File
@@ -19,6 +19,7 @@
- NodeJS:
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
- Misc:
- CHANGED: Partial fix migration from boost::optional to std::optional [#6551](https://github.com/Project-OSRM/osrm-backend/issues/6551), see also [#6592](https://github.com/Project-OSRM/osrm-backend/issues/6592)
- CHANGED: Update Conan Boost version to 1.85.0. [#6868](https://github.com/Project-OSRM/osrm-backend/pull/6868)
- FIXED: Fix an error in a RouteParameters AnnotationsType operator overload. [#6646](https://github.com/Project-OSRM/osrm-backend/pull/6646)
- ADDED: Add support for "unlimited" to be passed as a value for the default-radius and max-matching-radius flags. [#6599](https://github.com/Project-OSRM/osrm-backend/pull/6599)
@@ -49,6 +50,7 @@
- FIXED: Correctly check runtime search conditions for forcing routing steps [#6866](https://github.com/Project-OSRM/osrm-backend/pull/6866)
- Map Matching:
- CHANGED: Optimise path distance calculation in MLD map matching. [#6876](https://github.com/Project-OSRM/osrm-backend/pull/6876)
- CHANGED: Optimise R-tree queries in the case of map matching. [#6881](https://github.com/Project-OSRM/osrm-backend/pull/6876)
- Debug tiles:
- FIXED: Ensure speed layer features have unique ids. [#6726](https://github.com/Project-OSRM/osrm-backend/pull/6726)
+1 -1
View File
@@ -15,7 +15,7 @@ The following services are available via HTTP API, C++ library interface and Nod
To quickly try OSRM use our [demo server](http://map.project-osrm.org) which comes with both the backend and a frontend on top.
For a quick introduction about how the road network is represented in OpenStreetMap and how to map specific road network features have a look at [this guide about mapping for navigation](https://www.mapbox.com/mapping/mapping-for-navigation/).
For a quick introduction about how the road network is represented in OpenStreetMap and how to map specific road network features have a look at [the OSM wiki on routing](https://wiki.openstreetmap.org/wiki/Routing) or [this guide about mapping for navigation](https://web.archive.org/web/20221206013651/https://labs.mapbox.com/mapping/mapping-for-navigation/).
Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
- [osrm-frontend](https://github.com/Project-OSRM/osrm-frontend) - User-facing frontend with map. The demo server runs this on top of the backend
@@ -375,7 +375,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
BOOST_ASSERT(m_geospatial_query.get());
return m_geospatial_query->NearestPhantomNodes(
input_coordinate, approach, boost::none, max_distance, bearing, use_all_edges);
input_coordinate, approach, max_distance, bearing, use_all_edges);
}
std::vector<PhantomNodeWithDistance>
+34 -4
View File
@@ -47,12 +47,42 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
return rtree.SearchInBox(bbox);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const Approach approach,
const double max_distance,
const boost::optional<Bearing> bearing_with_range,
const boost::optional<bool> use_all_edges) const
{
auto results = rtree.SearchInRange(
input_coordinate,
max_distance,
[this, approach, &input_coordinate, &bearing_with_range, &use_all_edges, max_distance](
const CandidateSegment &segment)
{
auto invalidDistance =
CheckSegmentDistance(input_coordinate, segment, max_distance);
if (invalidDistance)
{
return std::make_pair(false, false);
}
auto valid = CheckSegmentExclude(segment) &&
CheckApproach(input_coordinate, segment, approach) &&
(use_all_edges ? HasValidEdge(segment, *use_all_edges)
: HasValidEdge(segment)) &&
(bearing_with_range ? CheckSegmentBearing(segment, *bearing_with_range)
: std::make_pair(true, true));
return valid;
});
return MakePhantomNodes(input_coordinate, results);
}
// Returns max_results nearest PhantomNodes that are valid within the provided parameters.
// Does not filter by small/big component!
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const Approach approach,
const boost::optional<size_t> max_results,
const size_t max_results,
const boost::optional<double> max_distance,
const boost::optional<Bearing> bearing_with_range,
const boost::optional<bool> use_all_edges) const
@@ -70,10 +100,10 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
: std::make_pair(true, true));
return valid;
},
[this, &max_distance, &max_results, input_coordinate](const std::size_t num_results,
const CandidateSegment &segment)
[this, &max_distance, max_results, input_coordinate](const std::size_t num_results,
const CandidateSegment &segment)
{
return (max_results && num_results >= *max_results) ||
return (num_results >= max_results) ||
(max_distance && max_distance != -1.0 &&
CheckSegmentDistance(input_coordinate, segment, *max_distance));
});
@@ -122,7 +122,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight;
if (new_weight < upper_bound)
{
if (shouldForceStep(force_step_nodes, heapNode, reverseHeapNode.get()) ||
if (shouldForceStep(force_step_nodes, heapNode, *reverseHeapNode) ||
// in this case we are looking at a bi-directional way where the source
// and target phantom are on the same edge based node
new_weight < EdgeWeight{0})
@@ -408,7 +408,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
auto reverse_weight = reverseHeapNode->weight;
auto path_weight = weight + reverse_weight;
if (!shouldForceStep(force_step_nodes, heapNode, reverseHeapNode.get()) &&
if (!shouldForceStep(force_step_nodes, heapNode, *reverseHeapNode) &&
(path_weight >= EdgeWeight{0}) && (path_weight < path_upper_bound))
{
middle_node = heapNode.node;
@@ -11,8 +11,8 @@
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
#include <boost/optional.hpp>
#include <cstdint>
#include <optional>
#include <utility>
namespace osrm::extractor::intersection
@@ -42,10 +42,10 @@ class NodeBasedGraphWalker
* selector not provinding any further edge to traverse)
*/
template <class accumulator_type, class selector_type>
boost::optional<std::pair<NodeID, EdgeID>> TraverseRoad(NodeID starting_at_node_id,
EdgeID following_edge_id,
accumulator_type &accumulator,
const selector_type &selector) const;
std::optional<std::pair<NodeID, EdgeID>> TraverseRoad(NodeID starting_at_node_id,
EdgeID following_edge_id,
accumulator_type &accumulator,
const selector_type &selector) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
@@ -111,11 +111,11 @@ struct SelectRoadByNameOnlyChoiceAndStraightness
* traversal. If no such edge is found, return {} is allowed. Usually you want to choose some
* form of obious turn to follow.
*/
boost::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const;
std::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const;
private:
const NameID desired_name_id;
@@ -138,11 +138,11 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
* traversal. If no such edge is found, return {} is allowed. Usually you want to choose some
* form of obious turn to follow.
*/
boost::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const;
std::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const;
private:
const NameID desired_name_id;
@@ -187,7 +187,7 @@ struct IntersectionFinderAccumulator
};
template <class accumulator_type, class selector_type>
boost::optional<std::pair<NodeID, EdgeID>>
std::optional<std::pair<NodeID, EdgeID>>
NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
EdgeID current_edge_id,
accumulator_type &accumulator,
@@ -254,19 +254,19 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
struct SkipTrafficSignalBarrierRoadSelector
{
boost::optional<EdgeID> operator()(const NodeID,
const EdgeID,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &,
const EdgeBasedNodeDataContainer &) const
std::optional<EdgeID> operator()(const NodeID,
const EdgeID,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &,
const EdgeBasedNodeDataContainer &) const
{
if (intersection.isTrafficSignalOrBarrier())
{
return boost::make_optional(intersection[1].eid);
return std::make_optional(intersection[1].eid);
}
else
{
return boost::none;
return std::nullopt;
}
}
};
@@ -3,7 +3,7 @@
#include "maneuver_override.hpp"
#include <boost/optional.hpp>
#include <optional>
#include <string>
#include <vector>
@@ -55,7 +55,7 @@ class ManeuverOverrideRelationParser
{
public:
ManeuverOverrideRelationParser();
boost::optional<InputManeuverOverride> TryParse(const osmium::Relation &relation) const;
std::optional<InputManeuverOverride> TryParse(const osmium::Relation &relation) const;
};
} // namespace osrm::extractor
+2 -2
View File
@@ -7,11 +7,11 @@
#include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/optional.hpp>
#include <algorithm>
#include <array>
#include <cstdint>
#include <optional>
namespace osrm::extractor
{
@@ -80,7 +80,7 @@ struct ProfileProperties
}
// Check if this classes are excludable
boost::optional<std::size_t> ClassesAreExcludable(ClassData classes) const
std::optional<std::size_t> ClassesAreExcludable(ClassData classes) const
{
auto iter = std::find(excludable_classes.begin(), excludable_classes.end(), classes);
if (iter != excludable_classes.end())
+2 -3
View File
@@ -15,11 +15,10 @@
#include <algorithm>
#include <cstddef>
#include <optional>
#include <utility>
#include <vector>
#include <boost/optional.hpp>
namespace osrm::guidance
{
@@ -129,7 +128,7 @@ class IntersectionHandler
// ^ via
//
// For this scenario returns intersection at `b` and `b`.
boost::optional<IntersectionHandler::IntersectionViewAndNode>
std::optional<IntersectionHandler::IntersectionViewAndNode>
getNextIntersection(const NodeID at, const EdgeID via) const;
bool isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const;
+4 -5
View File
@@ -9,10 +9,9 @@
#include "util/node_based_graph.hpp"
#include <optional>
#include <vector>
#include <boost/optional.hpp>
namespace osrm::guidance
{
@@ -43,9 +42,9 @@ class SliproadHandler final : public IntersectionHandler
Intersection intersection) const override final;
private:
boost::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from,
const Intersection &intersection,
const NodeID at) const;
std::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from,
const Intersection &intersection,
const NodeID at) const;
// Next intersection from `start` onto `onto` is too far away for a Siproad scenario
bool nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const;
+3 -4
View File
@@ -11,9 +11,8 @@
#include "util/attributes.hpp"
#include "util/node_based_graph.hpp"
#include <boost/optional.hpp>
#include <cstddef>
#include <optional>
#include <utility>
#include <vector>
@@ -72,7 +71,7 @@ class TurnHandler final : public IntersectionHandler
bool hasObvious(const EdgeID &via_edge, const Fork &fork) const;
boost::optional<Fork> findForkCandidatesByGeometry(Intersection &intersection) const;
std::optional<Fork> findForkCandidatesByGeometry(Intersection &intersection) const;
bool isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const;
@@ -96,7 +95,7 @@ class TurnHandler final : public IntersectionHandler
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
// Classification
boost::optional<Fork> findFork(const EdgeID via_edge, Intersection &intersection) const;
std::optional<Fork> findFork(const EdgeID via_edge, Intersection &intersection) const;
OSRM_ATTR_WARN_UNUSED
Intersection assignLeftTurns(const EdgeID via_edge,
+1 -1
View File
@@ -39,7 +39,7 @@ template <typename Key, typename Value> struct CSVFilesParser
{
}
// Operator returns a lambda function that maps input Key to boost::optional<Value>.
// Operator returns a lambda function that maps input Key to std::optional<Value>.
auto operator()(const std::vector<std::string> &csv_filenames) const
{
try
+4 -5
View File
@@ -3,8 +3,7 @@
#include "util/typedefs.hpp"
#include <boost/optional.hpp>
#include <optional>
#include <vector>
namespace osrm::updater
@@ -12,9 +11,9 @@ namespace osrm::updater
template <typename Key, typename Value> struct LookupTable
{
boost::optional<Value> operator()(const Key &key) const
std::optional<Value> operator()(const Key &key) const
{
using Result = boost::optional<Value>;
using Result = std::optional<Value>;
const auto it =
std::lower_bound(lookup.begin(),
lookup.end(),
@@ -50,7 +49,7 @@ struct SpeedSource final
{
SpeedSource() : speed(0.), rate() {}
double speed;
boost::optional<double> rate;
std::optional<double> rate;
std::uint8_t source;
};
+11 -4
View File
@@ -4,11 +4,11 @@
#include "util/coordinate.hpp"
#include <boost/math/constants/constants.hpp>
#include <boost/optional.hpp>
#include <algorithm>
#include <cmath>
#include <numeric>
#include <optional>
#include <utility>
#include <vector>
@@ -36,6 +36,13 @@ inline double radToDeg(const double radian)
}
} // namespace detail
const constexpr static double METERS_PER_DEGREE_LAT = 110567.0;
inline double metersPerLngDegree(const FixedLatitude lat)
{
return std::cos(detail::degToRad(static_cast<double>(toFloating(lat)))) * METERS_PER_DEGREE_LAT;
}
//! Takes the squared euclidean distance of the input coordinates. Does not return meters!
std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs);
@@ -102,9 +109,9 @@ double bearing(const Coordinate first_coordinate, const Coordinate second_coordi
double computeAngle(const Coordinate first, const Coordinate second, const Coordinate third);
// find the center of a circle through three coordinates
boost::optional<Coordinate> circleCenter(const Coordinate first_coordinate,
const Coordinate second_coordinate,
const Coordinate third_coordinate);
std::optional<Coordinate> circleCenter(const Coordinate first_coordinate,
const Coordinate second_coordinate,
const Coordinate third_coordinate);
// find the radius of a circle through three coordinates
double circleRadius(const Coordinate first_coordinate,
+5 -6
View File
@@ -1,6 +1,7 @@
#ifndef OSRM_GEOJSON_DEBUG_POLICIES
#define OSRM_GEOJSON_DEBUG_POLICIES
#include <optional>
#include <vector>
#include "extractor/query_node.hpp"
@@ -9,8 +10,6 @@
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include <boost/optional.hpp>
namespace osrm::util
{
@@ -20,7 +19,7 @@ struct NodeIdVectorToLineString
// converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties = {}) const;
const std::optional<json::Object> &properties = {}) const;
const std::vector<util::Coordinate> &node_coordinates;
};
@@ -29,7 +28,7 @@ struct CoordinateVectorToLineString
{
// converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
const boost::optional<json::Object> &properties = {}) const;
const std::optional<json::Object> &properties = {}) const;
};
struct NodeIdVectorToMultiPoint
@@ -38,7 +37,7 @@ struct NodeIdVectorToMultiPoint
// converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties = {}) const;
const std::optional<json::Object> &properties = {}) const;
const std::vector<util::Coordinate> &node_coordinates;
};
@@ -47,7 +46,7 @@ struct CoordinateVectorToMultiPoint
{
// converts a vector of node ids into a linestring geojson feature
util::json::Object operator()(const std::vector<util::Coordinate> &coordinates,
const boost::optional<json::Object> &properties = {}) const;
const std::optional<json::Object> &properties = {}) const;
};
} // namespace osrm::util
@@ -7,8 +7,7 @@
#include <algorithm>
#include <iterator>
#include <boost/optional.hpp>
#include <optional>
namespace osrm::util
{
@@ -84,7 +83,7 @@ struct NodeIdToCoordinate
inline util::json::Object makeFeature(std::string type,
util::json::Array coordinates,
const boost::optional<util::json::Object> &properties = {})
const std::optional<util::json::Object> &properties = {})
{
util::json::Object result;
result.values["type"] = "Feature";
+7 -7
View File
@@ -3,12 +3,12 @@
#include <boost/assert.hpp>
#include <boost/heap/d_ary_heap.hpp>
#include <boost/optional.hpp>
#include <algorithm>
#include <cstdint>
#include <limits>
#include <map>
#include <optional>
#include <unordered_map>
#include <vector>
@@ -290,26 +290,26 @@ class QueryHeap
return inserted_nodes[index].node == node;
}
boost::optional<HeapNode &> GetHeapNodeIfWasInserted(const NodeID node)
HeapNode *GetHeapNodeIfWasInserted(const NodeID node)
{
const auto index = node_index.peek_index(node);
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
inserted_nodes[index].node != node)
{
return {};
return nullptr;
}
return inserted_nodes[index];
return &inserted_nodes[index];
}
boost::optional<const HeapNode &> GetHeapNodeIfWasInserted(const NodeID node) const
const HeapNode *GetHeapNodeIfWasInserted(const NodeID node) const
{
const auto index = node_index.peek_index(node);
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
inserted_nodes[index].node != node)
{
return {};
return nullptr;
}
return inserted_nodes[index];
return &inserted_nodes[index];
}
NodeID Min() const
+12 -1
View File
@@ -3,7 +3,6 @@
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include <boost/assert.hpp>
#include <limits>
@@ -168,6 +167,18 @@ struct RectangleInt2D
min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::max()} &&
max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()};
}
static RectangleInt2D ExpandMeters(const Coordinate &coordinate, const double meters)
{
const double lat_offset = meters / coordinate_calculation::METERS_PER_DEGREE_LAT;
const double lon_offset =
meters / coordinate_calculation::metersPerLngDegree(coordinate.lat);
return RectangleInt2D{coordinate.lon - toFixed(FloatLongitude{lon_offset}),
coordinate.lon + toFixed(FloatLongitude{lon_offset}),
coordinate.lat - toFixed(FloatLatitude{lat_offset}),
coordinate.lat + toFixed(FloatLatitude{lat_offset})};
}
};
} // namespace osrm::util
+111 -64
View File
@@ -2,7 +2,6 @@
#define STATIC_RTREE_HPP
#include "storage/tar_fwd.hpp"
#include "util/bearing.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/deallocating_vector.hpp"
@@ -11,6 +10,7 @@
#include "util/integer_range.hpp"
#include "util/mmap_file.hpp"
#include "util/rectangle.hpp"
#include "util/timing_util.hpp"
#include "util/typedefs.hpp"
#include "util/vector_view.hpp"
#include "util/web_mercator.hpp"
@@ -487,70 +487,9 @@ class StaticRTree
Rectangle needs to be projected!*/
std::vector<EdgeDataT> SearchInBox(const Rectangle &search_rectangle) const
{
const Rectangle projected_rectangle{
search_rectangle.min_lon,
search_rectangle.max_lon,
toFixed(FloatLatitude{
web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.min_lat)))}),
toFixed(FloatLatitude{
web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.max_lat)))})};
std::vector<EdgeDataT> results;
std::queue<TreeIndex> traversal_queue;
traversal_queue.push(TreeIndex{});
while (!traversal_queue.empty())
{
auto const current_tree_index = traversal_queue.front();
traversal_queue.pop();
// If we're at the bottom of the tree, we need to explore the
// element array
if (is_leaf(current_tree_index))
{
// Note: irange is [start,finish), so we need to +1 to make sure we visit the
// last
for (const auto current_child_index : child_indexes(current_tree_index))
{
const auto &current_edge = m_objects[current_child_index];
// we don't need to project the coordinates here,
// because we use the unprojected rectangle to test against
const Rectangle bbox{std::min(m_coordinate_list[current_edge.u].lon,
m_coordinate_list[current_edge.v].lon),
std::max(m_coordinate_list[current_edge.u].lon,
m_coordinate_list[current_edge.v].lon),
std::min(m_coordinate_list[current_edge.u].lat,
m_coordinate_list[current_edge.v].lat),
std::max(m_coordinate_list[current_edge.u].lat,
m_coordinate_list[current_edge.v].lat)};
// use the _unprojected_ input rectangle here
if (bbox.Intersects(search_rectangle))
{
results.push_back(current_edge);
}
}
}
else
{
BOOST_ASSERT(current_tree_index.level + 1 < m_tree_level_starts.size());
for (const auto child_index : child_indexes(current_tree_index))
{
const auto &child_rectangle =
m_search_tree[child_index].minimum_bounding_rectangle;
if (child_rectangle.Intersects(projected_rectangle))
{
traversal_queue.push(TreeIndex(
current_tree_index.level + 1,
child_index - m_tree_level_starts[current_tree_index.level + 1]));
}
}
}
}
SearchInBox(search_rectangle,
[&results](const auto &edge_data) { results.push_back(edge_data); });
return results;
}
@@ -565,6 +504,45 @@ class StaticRTree
{ return num_results >= max_results; });
}
// NB 1: results are not guaranteed to be sorted by distance
// NB 2: maxDistanceMeters is not a hard limit, it's just a way to reduce the number of edges
// returned
template <typename FilterT>
std::vector<CandidateSegment> SearchInRange(const Coordinate input_coordinate,
double maxDistanceMeters,
const FilterT filter) const
{
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
Coordinate fixed_projected_coordinate{projected_coordinate};
auto bbox = Rectangle::ExpandMeters(input_coordinate, maxDistanceMeters);
std::vector<CandidateSegment> results;
SearchInBox(
bbox,
[&results, &filter, fixed_projected_coordinate, this](const EdgeDataT &current_edge)
{
const auto projected_u = web_mercator::fromWGS84(m_coordinate_list[current_edge.u]);
const auto projected_v = web_mercator::fromWGS84(m_coordinate_list[current_edge.v]);
auto [_, projected_nearest] = coordinate_calculation::projectPointOnSegment(
projected_u, projected_v, fixed_projected_coordinate);
CandidateSegment current_candidate{projected_nearest, current_edge};
auto use_segment = filter(current_candidate);
if (!use_segment.first && !use_segment.second)
{
return;
}
current_candidate.data.forward_segment_id.enabled &= use_segment.first;
current_candidate.data.reverse_segment_id.enabled &= use_segment.second;
results.push_back(current_candidate);
});
return results;
}
// Return edges in distance order with the coordinate of the closest point on the edge.
template <typename FilterT, typename TerminationT>
std::vector<CandidateSegment> Nearest(const Coordinate input_coordinate,
@@ -572,8 +550,10 @@ class StaticRTree
const TerminationT terminate) const
{
std::vector<CandidateSegment> results;
auto projected_coordinate = web_mercator::fromWGS84(input_coordinate);
Coordinate fixed_projected_coordinate{projected_coordinate};
// initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue;
traversal_queue.push(QueryCandidate{0, TreeIndex{}});
@@ -631,6 +611,73 @@ class StaticRTree
}
private:
template <typename Callback>
void SearchInBox(const Rectangle &search_rectangle, Callback &&callback) const
{
const Rectangle projected_rectangle{
search_rectangle.min_lon,
search_rectangle.max_lon,
toFixed(FloatLatitude{
web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.min_lat)))}),
toFixed(FloatLatitude{
web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.max_lat)))})};
std::queue<TreeIndex> traversal_queue;
traversal_queue.push(TreeIndex{});
while (!traversal_queue.empty())
{
auto const current_tree_index = traversal_queue.front();
traversal_queue.pop();
// If we're at the bottom of the tree, we need to explore the
// element array
if (is_leaf(current_tree_index))
{
// Note: irange is [start,finish), so we need to +1 to make sure we visit the
// last
for (const auto current_child_index : child_indexes(current_tree_index))
{
const auto &current_edge = m_objects[current_child_index];
// we don't need to project the coordinates here,
// because we use the unprojected rectangle to test against
const Rectangle bbox{std::min(m_coordinate_list[current_edge.u].lon,
m_coordinate_list[current_edge.v].lon),
std::max(m_coordinate_list[current_edge.u].lon,
m_coordinate_list[current_edge.v].lon),
std::min(m_coordinate_list[current_edge.u].lat,
m_coordinate_list[current_edge.v].lat),
std::max(m_coordinate_list[current_edge.u].lat,
m_coordinate_list[current_edge.v].lat)};
// use the _unprojected_ input rectangle here
if (bbox.Intersects(search_rectangle))
{
callback(current_edge);
}
}
}
else
{
BOOST_ASSERT(current_tree_index.level + 1 < m_tree_level_starts.size());
for (const auto child_index : child_indexes(current_tree_index))
{
const auto &child_rectangle =
m_search_tree[child_index].minimum_bounding_rectangle;
if (child_rectangle.Intersects(projected_rectangle))
{
traversal_queue.push(TreeIndex(
current_tree_index.level + 1,
child_index - m_tree_level_starts[current_tree_index.level + 1]));
}
}
}
}
}
/**
* Iterates over all the objects in a leaf node and inserts them into our
* search priority queue. The speed of this function is very much governed
+2 -2
View File
@@ -6,11 +6,11 @@
#include <boost/filesystem/path.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <boost/optional.hpp>
#include <rapidjson/document.h>
#include <chrono>
#include <optional>
namespace osrm::updater
{
@@ -34,7 +34,7 @@ class Timezoner
Timezoner(const char geojson[], std::time_t utc_time_now);
Timezoner(const boost::filesystem::path &tz_shapes_filename, std::time_t utc_time_now);
boost::optional<struct tm> operator()(const point_t &point) const;
std::optional<struct tm> operator()(const point_t &point) const;
private:
void LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t utc_time);
+96
View File
@@ -0,0 +1,96 @@
import requests
import os
import re
import sys
import json
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
REPO = os.getenv('GITHUB_REPOSITORY')
PR_NUMBER = os.getenv('PR_NUMBER')
REPO_OWNER, REPO_NAME = REPO.split('/')
def create_markdown_table(results):
results = sorted(results, key=lambda x: x['name'])
header = "| Benchmark | Base | PR |\n|-----------|------|----|"
rows = []
for result in results:
name = result['name']
base = result['base'].replace('\n', '<br/>')
pr = result['pr'].replace('\n', '<br/>')
row = f"| {name} | {base} | {pr} |"
rows.append(row)
return f"{header}\n" + "\n".join(rows)
def get_pr_details(repo_owner, repo_name, pr_number):
url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/pulls/{pr_number}"
headers = {'Authorization': f'token {GITHUB_TOKEN}'}
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
def update_pr_description(repo_owner, repo_name, pr_number, body):
url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/pulls/{pr_number}"
headers = {'Authorization': f'token {GITHUB_TOKEN}'}
data = {'body': body}
response = requests.patch(url, headers=headers, json=data)
response.raise_for_status()
return response.json()
def collect_benchmark_results(base_folder, pr_folder):
results = []
results_index = {}
for file in os.listdir(base_folder):
if not file.endswith('.bench'): continue
with open(f"{base_folder}/{file}") as f:
result = f.read().strip()
results.append({'base': result, 'pr': None, 'name': os.path.splitext(file)[0]})
results_index[file] = len(results) - 1
for file in os.listdir(pr_folder):
if not file.endswith('.bench'): continue
with open(f"{pr_folder}/{file}") as f:
result = f.read().strip()
if file in results_index:
results[results_index[file]]['pr'] = result
else:
results.append({'base': None, 'pr': result, 'name': os.path.splitext(file)[0]})
return results
def main():
if len(sys.argv) != 3:
print("Usage: python post_benchmark_results.py <base_folder> <pr_folder>")
exit(1)
base_folder = sys.argv[1]
pr_folder = sys.argv[2]
benchmark_results = collect_benchmark_results(base_folder, pr_folder)
pr_details = get_pr_details(REPO_OWNER, REPO_NAME, PR_NUMBER)
# in both cases when there is no PR body or PR body is None fallback to empty string
pr_body = pr_details.get('body', '') or ''
markdown_table = create_markdown_table(benchmark_results)
new_benchmark_section = f"<!-- BENCHMARK_RESULTS_START -->\n## Benchmark Results\n{markdown_table}\n<!-- BENCHMARK_RESULTS_END -->"
if re.search(r'<!-- BENCHMARK_RESULTS_START -->.*<!-- BENCHMARK_RESULTS_END -->', pr_body, re.DOTALL):
updated_body = re.sub(
r'<!-- BENCHMARK_RESULTS_START -->.*<!-- BENCHMARK_RESULTS_END -->',
new_benchmark_section,
pr_body,
flags=re.DOTALL
)
else:
updated_body = f"{pr_body}\n\n{new_benchmark_section}" if len(pr_body) > 0 else new_benchmark_section
update_pr_description(REPO_OWNER, REPO_NAME, PR_NUMBER, updated_body)
print("PR description updated successfully.")
if __name__ == "__main__":
main()
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
set -eou pipefail
function run_benchmarks_for_folder {
echo "Running benchmarks for $1"
FOLDER=$1
RESULTS_FOLDER=$2
mkdir -p $RESULTS_FOLDER
BENCHMARKS_FOLDER="$FOLDER/build/src/benchmarks"
./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/mld/monaco.osrm" mld > "$RESULTS_FOLDER/match_mld.bench"
./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/ch/monaco.osrm" ch > "$RESULTS_FOLDER/match_ch.bench"
./$BENCHMARKS_FOLDER/alias-bench > "$RESULTS_FOLDER/alias.bench"
./$BENCHMARKS_FOLDER/json-render-bench "./$FOLDER/src/benchmarks/portugal_to_korea.json" > "$RESULTS_FOLDER/json-render.bench"
./$BENCHMARKS_FOLDER/packedvector-bench > "$RESULTS_FOLDER/packedvector.bench"
./$BENCHMARKS_FOLDER/rtree-bench "./$FOLDER/test/data/monaco.osrm.ramIndex" "./$FOLDER/test/data/monaco.osrm.fileIndex" "./$FOLDER/test/data/monaco.osrm.nbg_nodes" > "$RESULTS_FOLDER/rtree.bench"
}
run_benchmarks_for_folder $1 "${1}_results"
run_benchmarks_for_folder $2 "${2}_results"
+4 -4
View File
@@ -64,7 +64,7 @@ int main(int, char **)
return EXIT_FAILURE;
}
TIMER_STOP(aliased_u32);
util::Log() << "aliased u32: " << TIMER_MSEC(aliased_u32);
std::cout << "aliased u32: " << TIMER_MSEC(aliased_u32) << std::endl;
TIMER_START(plain_u32);
for (auto round : util::irange(0, num_rounds))
@@ -83,7 +83,7 @@ int main(int, char **)
return EXIT_FAILURE;
}
TIMER_STOP(plain_u32);
util::Log() << "plain u32: " << TIMER_MSEC(plain_u32);
std::cout << "plain u32: " << TIMER_MSEC(plain_u32) << std::endl;
TIMER_START(aliased_double);
for (auto round : util::irange(0, num_rounds))
@@ -103,7 +103,7 @@ int main(int, char **)
return EXIT_FAILURE;
}
TIMER_STOP(aliased_double);
util::Log() << "aliased double: " << TIMER_MSEC(aliased_double);
std::cout << "aliased double: " << TIMER_MSEC(aliased_double) << std::endl;
TIMER_START(plain_double);
for (auto round : util::irange(0, num_rounds))
@@ -123,5 +123,5 @@ int main(int, char **)
return EXIT_FAILURE;
}
TIMER_STOP(plain_double);
util::Log() << "plain double: " << TIMER_MSEC(plain_double);
std::cout << "plain double: " << TIMER_MSEC(plain_double) << std::endl;
}
+43 -17
View File
@@ -12,13 +12,14 @@
#include <boost/assert.hpp>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <optional>
#include <stdexcept>
#include <string>
#include <utility>
#include <cstdlib>
int main(int argc, const char *argv[])
try
{
@@ -214,24 +215,49 @@ try
params.coordinates.push_back(
FloatCoordinate{FloatLongitude{7.415342330932617}, FloatLatitude{43.733251335381205}});
TIMER_START(routes);
auto NUM = 100;
for (int i = 0; i < NUM; ++i)
auto run_benchmark = [&](std::optional<double> radiusInMeters)
{
engine::api::ResultT result = json::Object();
const auto rc = osrm.Match(params, result);
auto &json_result = result.get<json::Object>();
if (rc != Status::Ok ||
json_result.values.at("matchings").get<json::Array>().values.size() != 1)
params.radiuses = {};
if (radiusInMeters)
{
return EXIT_FAILURE;
for (size_t index = 0; index < params.coordinates.size(); ++index)
{
params.radiuses.emplace_back(*radiusInMeters);
}
}
TIMER_START(routes);
auto NUM = 100;
for (int i = 0; i < NUM; ++i)
{
engine::api::ResultT result = json::Object();
const auto rc = osrm.Match(params, result);
auto &json_result = result.get<json::Object>();
if (rc != Status::Ok ||
json_result.values.at("matchings").get<json::Array>().values.size() != 1)
{
throw std::runtime_error{"Couldn't match"};
}
}
TIMER_STOP(routes);
if (radiusInMeters)
{
std::cout << "Radius " << *radiusInMeters << "m: " << std::endl;
}
else
{
std::cout << "Default radius: " << std::endl;
}
std::cout << (TIMER_MSEC(routes) / NUM) << "ms/req at " << params.coordinates.size()
<< " coordinate" << std::endl;
std::cout << (TIMER_MSEC(routes) / NUM / params.coordinates.size()) << "ms/coordinate"
<< std::endl;
};
for (auto radius : std::vector<std::optional<double>>{std::nullopt, 5.0, 10.0, 15.0, 30.0})
{
run_benchmark(radius);
}
TIMER_STOP(routes);
std::cout << (TIMER_MSEC(routes) / NUM) << "ms/req at " << params.coordinates.size()
<< " coordinate" << std::endl;
std::cout << (TIMER_MSEC(routes) / NUM / params.coordinates.size()) << "ms/coordinate"
<< std::endl;
return EXIT_SUCCESS;
}
@@ -239,4 +265,4 @@ catch (const std::exception &e)
{
std::cerr << "Error: " << e.what() << std::endl;
return EXIT_FAILURE;
}
}
+6 -6
View File
@@ -72,10 +72,10 @@ int main(int, char **)
auto write_slowdown = result_packed.random_write_ms / result_plain.random_write_ms;
auto read_slowdown = result_packed.random_read_ms / result_plain.random_read_ms;
util::Log() << "random write: std::vector " << result_plain.random_write_ms
<< " ms, util::packed_vector " << result_packed.random_write_ms << " ms. "
<< write_slowdown;
util::Log() << "random read: std::vector " << result_plain.random_read_ms
<< " ms, util::packed_vector " << result_packed.random_read_ms << " ms. "
<< read_slowdown;
std::cout << "random write:\nstd::vector " << result_plain.random_write_ms
<< " ms\nutil::packed_vector " << result_packed.random_write_ms << " ms\n"
<< "slowdown: " << write_slowdown << std::endl;
std::cout << "random read:\nstd::vector " << result_plain.random_read_ms
<< " ms\nutil::packed_vector " << result_packed.random_read_ms << " ms\n"
<< "slowdown: " << read_slowdown << std::endl;
}
+6 -11
View File
@@ -36,8 +36,6 @@ void benchmarkQuery(const std::vector<util::Coordinate> &queries,
const std::string &name,
QueryT query)
{
std::cout << "Running " << name << " with " << queries.size() << " coordinates: " << std::flush;
TIMER_START(query);
for (const auto &q : queries)
{
@@ -46,11 +44,9 @@ void benchmarkQuery(const std::vector<util::Coordinate> &queries,
}
TIMER_STOP(query);
std::cout << "Took " << TIMER_SEC(query) << " seconds "
<< "(" << TIMER_MSEC(query) << "ms"
<< ") -> " << TIMER_MSEC(query) / queries.size() << " ms/query "
<< "(" << TIMER_MSEC(query) << "ms"
<< ")" << std::endl;
std::cout << name << ":\n"
<< TIMER_MSEC(query) << "ms"
<< " -> " << TIMER_MSEC(query) / queries.size() << " ms/query" << std::endl;
}
void benchmark(BenchStaticRTree &rtree, unsigned num_queries)
@@ -65,11 +61,10 @@ void benchmark(BenchStaticRTree &rtree, unsigned num_queries)
util::FixedLatitude{lat_udist(mt_rand)});
}
benchmarkQuery(
queries, "1 result", [&rtree](const util::Coordinate &q) { return rtree.Nearest(q, 1); });
benchmarkQuery(queries,
"raw RTree queries (1 result)",
[&rtree](const util::Coordinate &q) { return rtree.Nearest(q, 1); });
benchmarkQuery(queries,
"raw RTree queries (10 results)",
"10 results",
[&rtree](const util::Coordinate &q) { return rtree.Nearest(q, 10); });
}
} // namespace osrm::benchmarks
@@ -66,7 +66,7 @@ SelectRoadByNameOnlyChoiceAndStraightness::SelectRoadByNameOnlyChoiceAndStraight
{
}
boost::optional<EdgeID> SelectRoadByNameOnlyChoiceAndStraightness::operator()(
std::optional<EdgeID> SelectRoadByNameOnlyChoiceAndStraightness::operator()(
const NodeID /*nid*/,
const EdgeID /*via_edge_id*/,
const IntersectionView &intersection,
@@ -118,7 +118,7 @@ SelectStraightmostRoadByNameAndOnlyChoice::SelectStraightmostRoadByNameAndOnlyCh
{
}
boost::optional<EdgeID> SelectStraightmostRoadByNameAndOnlyChoice::operator()(
std::optional<EdgeID> SelectStraightmostRoadByNameAndOnlyChoice::operator()(
const NodeID /*nid*/,
const EdgeID /*via_edge_id*/,
const IntersectionView &intersection,
@@ -241,7 +241,7 @@ boost::optional<EdgeID> SelectStraightmostRoadByNameAndOnlyChoice::operator()(
return {};
}
return is_only_choice_with_same_name ? boost::optional<EdgeID>(min_element->eid) : boost::none;
return is_only_choice_with_same_name ? std::optional<EdgeID>(min_element->eid) : std::nullopt;
}
// ---------------------------------------------------------------------------------
@@ -1,9 +1,9 @@
#include "extractor/maneuver_override_relation_parser.hpp"
#include "extractor/maneuver_override.hpp"
#include <boost/optional/optional.hpp>
#include <boost/ref.hpp>
#include <optional>
#include <osmium/osm.hpp>
#include <osmium/tags/filter.hpp>
#include <osmium/tags/taglist.hpp>
@@ -21,7 +21,7 @@ ManeuverOverrideRelationParser::ManeuverOverrideRelationParser() {}
* into an InputManeuverOverride object, if the relation is considered
* valid (i.e. has the minimum tags we expect).
*/
boost::optional<InputManeuverOverride>
std::optional<InputManeuverOverride>
ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const
{
@@ -35,7 +35,7 @@ ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const
if (osmium::tags::match_none_of(tag_list, filter))
// if it's not a maneuver, continue;
{
return boost::none;
return std::nullopt;
}
// we pretend every restriction is a conditional restriction. If we do not find any restriction,
@@ -130,7 +130,7 @@ ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const
}
else
{
return boost::none;
return std::nullopt;
}
return maneuver_override;
}
+4 -5
View File
@@ -427,7 +427,7 @@ void IntersectionHandler::assignTrivialTurns(const EdgeID via_eid,
}
}
boost::optional<IntersectionHandler::IntersectionViewAndNode>
std::optional<IntersectionHandler::IntersectionViewAndNode>
IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) const
{
// We use the intersection generator to jump over traffic signals, barriers. The intersection
@@ -450,7 +450,7 @@ IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) cons
if (intersection_parameters.node == SPECIAL_NODEID ||
intersection_parameters.edge == SPECIAL_EDGEID)
{
return boost::none;
return {};
}
auto intersection = extractor::intersection::getConnectedRoads<false>(node_based_graph,
@@ -465,11 +465,10 @@ IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) cons
if (intersection.size() <= 2 || intersection.isTrafficSignalOrBarrier())
{
return boost::none;
return {};
}
return boost::make_optional(
IntersectionViewAndNode{std::move(intersection), intersection_node});
return std::make_optional(IntersectionViewAndNode{std::move(intersection), intersection_node});
}
bool IntersectionHandler::isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const
+9 -9
View File
@@ -634,7 +634,7 @@ Intersection SliproadHandler::operator()(const NodeID /*nid*/,
// Implementation details
boost::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads(
std::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads(
const EdgeID from, const Intersection &intersection, const NodeID at) const
{
BOOST_ASSERT(from != SPECIAL_EDGEID);
@@ -645,14 +645,14 @@ boost::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads(
if (index != 0)
{
return boost::make_optional(index);
return std::make_optional(index);
}
// Otherwise check if the road is forking into two and one of them is a Sliproad;
// then the non-Sliproad is the obvious one.
if (intersection.size() != 3)
{
return boost::none;
return {};
}
const auto forking = intersection[1].instruction.type == TurnType::Fork &&
@@ -660,7 +660,7 @@ boost::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads(
if (!forking)
{
return boost::none;
return {};
}
const auto first = getNextIntersection(at, intersection.getRightmostRoad().eid);
@@ -668,27 +668,27 @@ boost::optional<std::size_t> SliproadHandler::getObviousIndexWithSliproads(
if (!first || !second)
{
return boost::none;
return {};
}
if (first->intersection.isDeadEnd() || second->intersection.isDeadEnd())
{
return boost::none;
return {};
}
// In case of loops at the end of the road, we will arrive back at the intersection
// itself. If that is the case, the road is obviously not a sliproad.
if (canBeTargetOfSliproad(first->intersection) && at != second->node)
{
return boost::make_optional(std::size_t{2});
return std::make_optional(std::size_t{2});
}
if (canBeTargetOfSliproad(second->intersection) && at != first->node)
{
return boost::make_optional(std::size_t{1});
return std::make_optional(std::size_t{1});
}
return boost::none;
return {};
}
bool SliproadHandler::nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const
+6 -6
View File
@@ -6,10 +6,10 @@
#include <algorithm>
#include <limits>
#include <optional>
#include <utility>
#include <boost/assert.hpp>
#include <boost/optional.hpp>
using osrm::util::angularDeviation;
@@ -590,7 +590,7 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge,
}
// finds a fork candidate by just looking at the geometry and angle of an intersection
boost::optional<TurnHandler::Fork>
std::optional<TurnHandler::Fork>
TurnHandler::findForkCandidatesByGeometry(Intersection &intersection) const
{
if (intersection.size() >= 3)
@@ -647,7 +647,7 @@ TurnHandler::findForkCandidatesByGeometry(Intersection &intersection) const
}
}
}
return boost::none;
return {};
}
// check if the fork candidates (all roads between left and right) and the
@@ -695,8 +695,8 @@ bool TurnHandler::isCompatibleByRoadClass(const Intersection &intersection, cons
// Checks whether a three-way-intersection coming from `via_edge` is a fork
// with `intersection` as described as in #IntersectionExplanation@intersection_handler.hpp
boost::optional<TurnHandler::Fork> TurnHandler::findFork(const EdgeID via_edge,
Intersection &intersection) const
std::optional<TurnHandler::Fork> TurnHandler::findFork(const EdgeID via_edge,
Intersection &intersection) const
{
auto fork = findForkCandidatesByGeometry(intersection);
if (fork)
@@ -740,7 +740,7 @@ boost::optional<TurnHandler::Fork> TurnHandler::findFork(const EdgeID via_edge,
}
}
return boost::none;
return {};
}
void TurnHandler::handleDistinctConflict(const EdgeID via_edge,
+68
View File
@@ -0,0 +1,68 @@
#ifndef OSRM_BINDINGS_NODE_JSON_V8_RENDERER_HPP
#define OSRM_BINDINGS_NODE_JSON_V8_RENDERER_HPP
#include "osrm/json_container.hpp"
#include <napi.h>
#include <functional>
namespace node_osrm
{
struct V8Renderer
{
explicit V8Renderer(const Napi::Env &env, Napi::Value &out) : env(env), out(out) {}
void operator()(const osrm::json::String &string) const
{
out = Napi::String::New(env, string.value);
}
void operator()(const osrm::json::Number &number) const
{
out = Napi::Number::New(env, number.value);
}
void operator()(const osrm::json::Object &object) const
{
Napi::Object obj = Napi::Object::New(env);
for (const auto &keyValue : object.values)
{
Napi::Value child;
mapbox::util::apply_visitor(V8Renderer(env, child), keyValue.second);
obj.Set(keyValue.first, child);
}
out = obj;
}
void operator()(const osrm::json::Array &array) const
{
Napi::Array a = Napi::Array::New(env, array.values.size());
for (auto i = 0u; i < array.values.size(); ++i)
{
Napi::Value child;
mapbox::util::apply_visitor(V8Renderer(env, child), array.values[i]);
a.Set(i, child);
}
out = a;
}
void operator()(const osrm::json::True &) const { out = Napi::Boolean::New(env, true); }
void operator()(const osrm::json::False &) const { out = Napi::Boolean::New(env, false); }
void operator()(const osrm::json::Null &) const { out = env.Null(); }
private:
const Napi::Env &env;
Napi::Value &out;
};
inline void renderToV8(const Napi::Env &env, Napi::Value &out, const osrm::json::Object &object)
{
V8Renderer renderer(env, out);
renderer(object);
}
} // namespace node_osrm
#endif // JSON_V8_RENDERER_HPP
+32
View File
@@ -0,0 +1,32 @@
#ifndef OSRM_BINDINGS_NODE_HPP
#define OSRM_BINDINGS_NODE_HPP
#include "osrm/osrm_fwd.hpp"
#include <napi.h>
#include <memory>
namespace node_osrm
{
class Engine final : public Napi::ObjectWrap<Engine>
{
public:
static Napi::Object Init(Napi::Env env, Napi::Object exports);
Engine(const Napi::CallbackInfo &info);
std::shared_ptr<osrm::OSRM> this_;
private:
Napi::Value route(const Napi::CallbackInfo &info);
Napi::Value nearest(const Napi::CallbackInfo &info);
Napi::Value table(const Napi::CallbackInfo &info);
Napi::Value tile(const Napi::CallbackInfo &info);
Napi::Value match(const Napi::CallbackInfo &info);
Napi::Value trip(const Napi::CallbackInfo &info);
};
} // namespace node_osrm
#endif
File diff suppressed because it is too large Load Diff
+6 -5
View File
@@ -9,6 +9,7 @@
#include <algorithm>
#include <iterator>
#include <limits>
#include <optional>
#include <utility>
namespace osrm::util::coordinate_calculation
@@ -173,14 +174,14 @@ double computeAngle(const Coordinate first, const Coordinate second, const Coord
return angle;
}
boost::optional<Coordinate>
std::optional<Coordinate>
circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3)
{
// free after http://paulbourke.net/geometry/circlesphere/
// require three distinct points
if (C1 == C2 || C2 == C3 || C1 == C3)
{
return boost::none;
return {};
}
// define line through c1, c2 and c2,c3
@@ -195,7 +196,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3)
(std::abs(C2C1_lat) < std::numeric_limits<double>::epsilon() &&
std::abs(C3C2_lat) < std::numeric_limits<double>::epsilon()))
{
return boost::none;
return {};
}
else if (std::abs(C2C1_lon) < std::numeric_limits<double>::epsilon())
{
@@ -233,7 +234,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3)
// can this ever happen?
if (std::abs(C2C1_slope - C3C2_slope) < std::numeric_limits<double>::epsilon())
return boost::none;
return {};
const double C1_y = static_cast<double>(toFloating(C1.lat));
const double C1_x = static_cast<double>(toFloating(C1.lon));
@@ -247,7 +248,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3)
(2 * (C3C2_slope - C2C1_slope));
const double lat = (0.5 * (C1_x + C2_x) - lon) / C2C1_slope + 0.5 * (C1_y + C2_y);
if (lon < -180.0 || lon > 180.0 || lat < -90.0 || lat > 90.0)
return boost::none;
return {};
else
return Coordinate(FloatLongitude{lon}, FloatLatitude{lat});
}
+4 -4
View File
@@ -17,7 +17,7 @@ NodeIdVectorToLineString::NodeIdVectorToLineString(
// converts a vector of node ids into a linestring geojson feature
util::json::Object
NodeIdVectorToLineString::operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties) const
const std::optional<json::Object> &properties) const
{
util::json::Array coordinates;
std::transform(node_ids.begin(),
@@ -37,7 +37,7 @@ NodeIdVectorToMultiPoint::NodeIdVectorToMultiPoint(
util::json::Object
NodeIdVectorToMultiPoint::operator()(const std::vector<NodeID> &node_ids,
const boost::optional<json::Object> &properties) const
const std::optional<json::Object> &properties) const
{
util::json::Array coordinates;
std::transform(node_ids.begin(),
@@ -51,7 +51,7 @@ NodeIdVectorToMultiPoint::operator()(const std::vector<NodeID> &node_ids,
//----------------------------------------------------------------
util::json::Object
CoordinateVectorToMultiPoint::operator()(const std::vector<util::Coordinate> &input_coordinates,
const boost::optional<json::Object> &properties) const
const std::optional<json::Object> &properties) const
{
auto coordinates = makeJsonArray(input_coordinates);
return makeFeature("MultiPoint", std::move(coordinates), properties);
@@ -60,7 +60,7 @@ CoordinateVectorToMultiPoint::operator()(const std::vector<util::Coordinate> &in
//----------------------------------------------------------------
util::json::Object
CoordinateVectorToLineString::operator()(const std::vector<util::Coordinate> &input_coordinates,
const boost::optional<json::Object> &properties) const
const std::optional<json::Object> &properties) const
{
auto coordinates = makeJsonArray(input_coordinates);
return makeFeature("LineString", std::move(coordinates), properties);
+3 -3
View File
@@ -5,13 +5,13 @@
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/optional.hpp>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <rapidjson/istreamwrapper.h>
#include <fstream>
#include <optional>
#include <regex>
#include <string>
#include <unordered_map>
@@ -158,7 +158,7 @@ void Timezoner::LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t ut
rtree = rtree_t(polygons);
}
boost::optional<struct tm> Timezoner::operator()(const point_t &point) const
std::optional<struct tm> Timezoner::operator()(const point_t &point) const
{
std::vector<rtree_t::value_type> result;
rtree.query(boost::geometry::index::intersects(point), std::back_inserter(result));
@@ -168,6 +168,6 @@ boost::optional<struct tm> Timezoner::operator()(const point_t &point) const
if (boost::geometry::within(point, local_times[index].first))
return local_times[index].second;
}
return boost::none;
return {};
}
} // namespace osrm::updater
+52 -16
View File
@@ -348,7 +348,13 @@ BOOST_AUTO_TEST_CASE(radius_regression_test)
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, boost::none, 0.01, boost::none, true);
input, osrm::engine::Approach::UNRESTRICTED, 0.01, boost::none, true);
BOOST_CHECK_EQUAL(results.size(), 0);
}
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, 1, 0.01, boost::none, true);
BOOST_CHECK_EQUAL(results.size(), 0);
}
}
@@ -374,13 +380,25 @@ BOOST_AUTO_TEST_CASE(permissive_edge_snapping)
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, boost::none, 1000, boost::none, false);
input, osrm::engine::Approach::UNRESTRICTED, 1000, boost::none, false);
BOOST_CHECK_EQUAL(results.size(), 1);
}
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, boost::none, 1000, boost::none, true);
input, osrm::engine::Approach::UNRESTRICTED, 1000, boost::none, true);
BOOST_CHECK_EQUAL(results.size(), 2);
}
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, 10, 1000, boost::none, false);
BOOST_CHECK_EQUAL(results.size(), 1);
}
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, 10, 1000, boost::none, true);
BOOST_CHECK_EQUAL(results.size(), 2);
}
}
@@ -442,27 +460,45 @@ BOOST_AUTO_TEST_CASE(bearing_tests)
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, boost::none, 11000, boost::none, true);
input, osrm::engine::Approach::UNRESTRICTED, 11000, boost::none, true);
BOOST_CHECK_EQUAL(results.size(), 2);
}
{
auto results = query.NearestPhantomNodes(input,
osrm::engine::Approach::UNRESTRICTED,
boost::none,
11000,
engine::Bearing{270, 10},
true);
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, 10, 11000, boost::none, true);
BOOST_CHECK_EQUAL(results.size(), 2);
}
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, 11000, engine::Bearing{270, 10}, true);
BOOST_CHECK_EQUAL(results.size(), 0);
}
{
auto results = query.NearestPhantomNodes(input,
osrm::engine::Approach::UNRESTRICTED,
boost::none,
11000,
engine::Bearing{45, 10},
true);
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, 10, 11000, engine::Bearing{270, 10}, true);
BOOST_CHECK_EQUAL(results.size(), 0);
}
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, 11000, engine::Bearing{45, 10}, true);
BOOST_CHECK_EQUAL(results.size(), 2);
BOOST_CHECK(results[0].phantom_node.forward_segment_id.enabled);
BOOST_CHECK(!results[0].phantom_node.reverse_segment_id.enabled);
BOOST_CHECK_EQUAL(results[0].phantom_node.forward_segment_id.id, 1);
BOOST_CHECK(!results[1].phantom_node.forward_segment_id.enabled);
BOOST_CHECK(results[1].phantom_node.reverse_segment_id.enabled);
BOOST_CHECK_EQUAL(results[1].phantom_node.reverse_segment_id.id, 1);
}
{
auto results = query.NearestPhantomNodes(
input, osrm::engine::Approach::UNRESTRICTED, 10, 11000, engine::Bearing{45, 10}, true);
BOOST_CHECK_EQUAL(results.size(), 2);
BOOST_CHECK(results[0].phantom_node.forward_segment_id.enabled);