diff options
Diffstat (limited to 'server/src/geo')
| -rw-r--r-- | server/src/geo/multizonal.cppm | 63 |
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 | ||
| 244 | template<class T> | ||
| 245 | class point_rtree | ||
| 246 | { | ||
| 247 | public: | ||
| 248 | using index_value = std::tuple<utm::zone_local::prim::box, utm::zone_local::prim::point, T>; | ||
| 249 | |||
| 250 | private: | ||
| 251 | multi_zone<bgeo::index::rtree<index_value, bgeo::index::quadratic<16>>> local_rtrees_; | ||
| 252 | |||
| 253 | public: | ||
| 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 |