rtree.h Source File

CPP API: rtree.h Source File
rtree.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Kilian Volmer
5 *
6 * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 #ifndef MIO_GEOGRAPHY_RTREE_H
21 #define MIO_GEOGRAPHY_RTREE_H
22 
25 
26 #include <boost/geometry/geometries/multi_polygon.hpp>
27 #include <boost/geometry/geometry.hpp>
28 #include <boost/geometry/index/rtree.hpp>
29 #include <boost/geometry/strategies/cartesian/buffer_side_straight.hpp>
30 #include <boost/geometry/strategies/geographic/buffer_point_circle.hpp>
31 
32 #include <cmath>
33 #include <iterator>
34 #include <type_traits>
35 #include <vector>
36 
37 namespace mio
38 {
39 namespace geo
40 {
46 template <class Location>
47 concept IsSphericalLocation = requires(const Location& loc) {
48  std::is_floating_point_v<decltype(loc.get_latitude())> && std::is_floating_point_v<decltype(loc.get_longitude())>;
49 };
50 
60 class RTree
61 {
62 public:
67  RTree() = default;
68 
74  template <IsSphericalLocation Location>
75  RTree(const std::vector<Location>& locations)
76  : m_rtree{}
77  {
78  for (size_t index = 0; index < locations.size(); index++) {
79  Point point(locations[index].get_longitude(), locations[index].get_latitude());
80  m_rtree.insert(Node(point, index));
81  }
82  }
83 
89  auto size() const
90  {
91  return m_rtree.size();
92  }
93 
101  std::vector<size_t> nearest_neighbor_indices(const IsSphericalLocation auto& location, size_t number) const
102  {
103  using boost::geometry::index::nearest;
104  using boost::geometry::index::query;
105 
106  Point point(location.get_longitude(), location.get_latitude());
107  std::vector<size_t> indices;
108  query(m_rtree, nearest(point, number), mio::back_inserter_second_element<std::vector<size_t>, Node>{indices});
109  return indices;
110  }
111 
119  std::vector<size_t> in_range_indices_approximate(const IsSphericalLocation auto& location, Distance radius) const
120  {
121  using boost::geometry::index::covered_by;
122  using boost::geometry::index::query;
123 
124  auto circle = create_circle_approximation(location, radius);
125  std::vector<size_t> indices;
126  query(m_rtree, covered_by(circle), mio::back_inserter_second_element<std::vector<size_t>, Node>{indices});
127  return indices;
128  }
129 
137  std::vector<std::vector<size_t>> in_range_indices_query(const IsSphericalLocation auto& location,
138  const std::vector<Distance>& radii) const
139  {
140  using boost::geometry::distance;
141  using boost::geometry::index::covered_by;
142  using boost::geometry::index::query;
143 
144  auto max_radius = std::max_element(radii.begin(), radii.end());
145  auto circle = create_circle_approximation(location, *max_radius);
146  std::vector<Node> nodes;
147  query(m_rtree, covered_by(circle), std::back_inserter(nodes));
148  auto midpoint = Point(location.get_longitude(), location.get_latitude());
149  std::vector<std::vector<size_t>> result;
150  for (const auto& radius : radii) {
151  auto radius_in_meter = radius.meters();
152  std::vector<size_t> indices;
153  indices.reserve(nodes.size());
154  for (auto& node : nodes) {
155  if (distance(midpoint, node.first) < radius_in_meter) {
156  indices.push_back(node.second);
157  }
158  }
159  result.push_back(indices);
160  }
161  return result;
162  }
163 
173  std::vector<size_t> in_range_indices(const IsSphericalLocation auto& location, Distance radius) const
174  {
175  using boost::geometry::distance;
176  using boost::geometry::index::covered_by;
177  using boost::geometry::index::query;
178 
179  auto circle = create_circle_approximation(location, radius);
180 
181  std::vector<Node> nodes;
182  query(m_rtree, covered_by(circle), std::back_inserter(nodes));
183  auto midpoint = Point(location.get_longitude(), location.get_latitude());
184  std::vector<size_t> indices;
185  indices.reserve(nodes.size());
186  for (auto& node : nodes) {
187  if (distance(midpoint, node.first) < radius.meters()) {
188  indices.push_back(node.second);
189  }
190  }
191  return indices;
192  }
193 
194 private:
196  using Point = boost::geometry::model::point<double, 2, boost::geometry::cs::geographic<boost::geometry::degree>>;
198  using Node = std::pair<Point, size_t>;
200  using MultiPolygon = boost::geometry::model::multi_polygon<boost::geometry::model::polygon<Point>>;
210  size_t approximation_points = 36) const
211  {
212  using namespace boost::geometry::strategy::buffer;
213 
214  geographic_point_circle<> point_strategy(approximation_points);
215  distance_symmetric<double> distance_strategy(radius.meters());
216  join_round join_strategy;
217  end_round end_strategy;
218  side_straight side_strategy;
219 
220  Point midpoint(location.get_longitude(), location.get_latitude());
221 
222  MultiPolygon circle;
223  boost::geometry::buffer(midpoint, circle, distance_strategy, side_strategy, join_strategy, end_strategy,
224  point_strategy);
225  return circle;
226  }
227 
228  // Arbitrarily chosen value - can be changed for better performance in different use cases.
229  constexpr static size_t m_max_number_of_elements_per_tree_node = 16;
230  boost::geometry::index::rtree<Node, boost::geometry::index::rstar<m_max_number_of_elements_per_tree_node>> m_rtree;
231 };
232 
233 } // namespace geo
234 } // namespace mio
235 
236 #endif // MIO_GEOGRAPHY_RTREE_H
All Locations in the simulated Model where Persons gather.
Definition: location.h:92
Represents a distance.
Definition: distance.h:37
ScalarType meters() const
return distance in meters.
Definition: distance.h:63
R-tree for spatial queries of geographical locations on the sphere.
Definition: rtree.h:61
constexpr static size_t m_max_number_of_elements_per_tree_node
Definition: rtree.h:229
std::vector< size_t > nearest_neighbor_indices(const IsSphericalLocation auto &location, size_t number) const
Return the indices of the k nearest neighbors (i.e.
Definition: rtree.h:101
std::vector< size_t > in_range_indices(const IsSphericalLocation auto &location, Distance radius) const
Return the indices of the points within a given radius.
Definition: rtree.h:173
std::vector< std::vector< size_t > > in_range_indices_query(const IsSphericalLocation auto &location, const std::vector< Distance > &radii) const
Return the indices of the points within each given radius for multiple radii at the same time.
Definition: rtree.h:137
std::vector< size_t > in_range_indices_approximate(const IsSphericalLocation auto &location, Distance radius) const
Return the indices of the points within a given radius (in kilometers) where the circle is approximat...
Definition: rtree.h:119
MultiPolygon create_circle_approximation(const IsSphericalLocation auto &location, Distance radius, size_t approximation_points=36) const
Create a circle approximation object.
Definition: rtree.h:209
std::pair< Point, size_t > Node
Node stores a point and its associated index.
Definition: rtree.h:198
auto size() const
Return the number of data points stored in the RTree.
Definition: rtree.h:89
boost::geometry::model::point< double, 2, boost::geometry::cs::geographic< boost::geometry::degree > > Point
Point stores longitude and latitude in this order.
Definition: rtree.h:196
boost::geometry::index::rtree< Node, boost::geometry::index::rstar< m_max_number_of_elements_per_tree_node > > m_rtree
Definition: rtree.h:230
RTree(const std::vector< Location > &locations)
Construct a new RTree object with data given in a vector.
Definition: rtree.h:75
boost::geometry::model::multi_polygon< boost::geometry::model::polygon< Point > > MultiPolygon
MultiPolygon type for circle approximation.
Definition: rtree.h:200
RTree()=default
Construct a new RTree object without data.
concept IsSphericalLocation
Concept for spherical location types.
Definition: rtree.h:47
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
requires(!std::is_trivial_v< T >) void BinarySerializerObject
Definition: binary_serializer.h:333
Back inserter that ignores the first element of pairs given to it.
Definition: back_inserter_second_element.h:33