summaryrefslogtreecommitdiffstats
path: root/server/src/geo/multizonal.cppm
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/geo/multizonal.cppm')
-rw-r--r--server/src/geo/multizonal.cppm63
1 files changed, 63 insertions, 0 deletions
diff --git a/server/src/geo/multizonal.cppm b/server/src/geo/multizonal.cppm
index ed78a24..7930367 100644
--- a/server/src/geo/multizonal.cppm
+++ b/server/src/geo/multizonal.cppm
@@ -241,4 +241,67 @@ public:
241 } 241 }
242}; 242};
243 243
244template<class T>
245class point_rtree
246{
247public:
248 using index_value = std::tuple<utm::zone_local::prim::box, utm::zone_local::prim::point, T>;
249
250private:
251 multi_zone<bgeo::index::rtree<index_value, bgeo::index::quadratic<16>>> local_rtrees_;
252
253public:
254 template<std::convertible_to<T> U>
255 auto insert(utm::zonable_wgs84_point const& p, U&& arg) -> void
256 {
257 auto to_utm = wgs84::utm_transforms::instance();
258
259 auto p_zone = utm::zone::for_wgs84_point(p);
260 auto mp_alt_zone = std::optional<utm::zone>{};
261 if (auto [neighbor_zone, neighbor_zone_dist] = wgs84::neighbor_utm_zone(p);
262 neighbor_zone_dist < 30.0 /* m */)
263 mp_alt_zone = neighbor_zone;
264
265 auto insert = [&](utm::zone z) -> void
266 {
267 auto p_utm = to_utm[z].apply(p);
268 auto bpe = bgeo::return_buffer<utm::zone_local::prim::box>(bgeo::return_envelope<utm::zone_local::prim::box>(p_utm), 30.0 /* m */);
269 local_rtrees_[z].insert(index_value{bpe, p_utm, arg});
270 };
271
272 insert(p_zone);
273 if (mp_alt_zone)
274 insert(*mp_alt_zone);
275 }
276
277 auto size() const -> std::size_t
278 {
279 auto total_size = 0uz;
280 for (auto z = utm::zone::min(); z != utm::zone::max(); z = z.next())
281 total_size += local_rtrees_[z].size();
282 return total_size;
283 }
284
285 // Note: the same T may be generated more than once!
286 auto intersection(zoned_linestring_seg_seq const& lss) const -> std::generator<T const&>
287 {
288 for (auto const& ls : lss.segments)
289 {
290 // auto ls_box = bgeo::return_envelope<utm::zone_local::prim::box>(ls);
291 for (auto it = local_rtrees_[ls.zone].qbegin(bgeo::index::intersects(ls));
292 it != local_rtrees_[ls.zone].qend(); it++)
293 {
294 using multi_linestring = bgeo::model::multi_linestring<utm::zone_local::prim::linestring>;
295
296 auto relevant_ls_parts = multi_linestring{};
297 bgeo::intersection(std::get<0>(*it), static_cast<utm::zone_local::prim::linestring const&>(ls), relevant_ls_parts);
298 if (bgeo::distance(relevant_ls_parts, std::get<1>(*it)) < 30.0 /* m */)
299 {
300 co_yield std::get<2>(*it);
301 }
302 }
303 }
304 }
305};
306
244} // namespace routemon::geo::multizonal 307} // namespace routemon::geo::multizonal