File indexing completed on 2025-01-18 09:35:06
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_GC_HPP
0010 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_GC_HPP
0011
0012
0013 #include <tuple>
0014
0015 #include <boost/range/size.hpp>
0016
0017 #include <boost/geometry/algorithms/detail/gc_make_rtree.hpp>
0018 #include <boost/geometry/algorithms/detail/intersection/interface.hpp>
0019 #include <boost/geometry/views/detail/geometry_collection_view.hpp>
0020
0021
0022 namespace boost { namespace geometry
0023 {
0024
0025 #ifndef DOXYGEN_NO_DETAIL
0026 namespace detail { namespace intersection
0027 {
0028
0029
0030 template <typename GC, typename Multi>
0031 struct gc_can_move_element
0032 {
0033 template <typename G>
0034 using is_same_as_single = std::is_same<G, typename boost::range_value<Multi>::type>;
0035 using gc_types = typename traits::geometry_types<GC>::type;
0036 using found_type = typename util::sequence_find_if<gc_types, is_same_as_single>::type;
0037 static const bool value = ! std::is_void<found_type>::value;
0038 };
0039
0040 template <typename GC, typename Multi>
0041 struct gc_can_convert_element
0042 {
0043 template <typename G>
0044 using has_same_tag_as_single = std::is_same
0045 <
0046 typename geometry::tag<G>::type,
0047 typename geometry::tag<typename boost::range_value<Multi>::type>::type
0048 >;
0049 using gc_types = typename traits::geometry_types<GC>::type;
0050 using found_type = typename util::sequence_find_if<gc_types, has_same_tag_as_single>::type;
0051 static const bool value = ! std::is_void<found_type>::value;
0052 };
0053
0054 template
0055 <
0056 typename GC, typename Multi,
0057 std::enable_if_t<gc_can_move_element<GC, Multi>::value, int> = 0
0058 >
0059 inline void gc_move_one_elem_multi_back(GC& gc, Multi&& multi)
0060 {
0061 range::emplace_back(gc, std::move(*boost::begin(multi)));
0062 }
0063
0064 template
0065 <
0066 typename GC, typename Multi,
0067 std::enable_if_t<! gc_can_move_element<GC, Multi>::value && gc_can_convert_element<GC, Multi>::value, int> = 0
0068 >
0069 inline void gc_move_one_elem_multi_back(GC& gc, Multi&& multi)
0070 {
0071 typename gc_can_convert_element<GC, Multi>::found_type single_out;
0072 geometry::convert(*boost::begin(multi), single_out);
0073 range::emplace_back(gc, std::move(single_out));
0074 }
0075
0076 template
0077 <
0078 typename GC, typename Multi,
0079 std::enable_if_t<! gc_can_move_element<GC, Multi>::value && ! gc_can_convert_element<GC, Multi>::value, int> = 0
0080 >
0081 inline void gc_move_one_elem_multi_back(GC& gc, Multi&& multi)
0082 {
0083 range::emplace_back(gc, std::move(multi));
0084 }
0085
0086 template <typename GC, typename Multi>
0087 inline void gc_move_multi_back(GC& gc, Multi&& multi)
0088 {
0089 if (! boost::empty(multi))
0090 {
0091 if (boost::size(multi) == 1)
0092 {
0093 gc_move_one_elem_multi_back(gc, std::move(multi));
0094 }
0095 else
0096 {
0097 range::emplace_back(gc, std::move(multi));
0098 }
0099 }
0100 }
0101
0102
0103 }}
0104 #endif
0105
0106
0107 namespace resolve_collection
0108 {
0109
0110
0111 template
0112 <
0113 typename Geometry1, typename Geometry2, typename GeometryOut
0114 >
0115 struct intersection
0116 <
0117 Geometry1, Geometry2, GeometryOut,
0118 geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
0119 >
0120 {
0121
0122
0123 using multi_point_t = typename util::sequence_find_if
0124 <
0125 typename traits::geometry_types<GeometryOut>::type,
0126 util::is_multi_point
0127 >::type;
0128 using multi_linestring_t = typename util::sequence_find_if
0129 <
0130 typename traits::geometry_types<GeometryOut>::type,
0131 util::is_multi_linestring
0132 >::type;
0133 using multi_polygon_t = typename util::sequence_find_if
0134 <
0135 typename traits::geometry_types<GeometryOut>::type,
0136 util::is_multi_polygon
0137 >::type;
0138 using tuple_out_t = boost::tuple<multi_point_t, multi_linestring_t, multi_polygon_t>;
0139
0140 template <typename Strategy>
0141 static inline bool apply(Geometry1 const& geometry1,
0142 Geometry2 const& geometry2,
0143 GeometryOut& geometry_out,
0144 Strategy const& strategy)
0145 {
0146 bool result = false;
0147 tuple_out_t out;
0148
0149 auto const rtree2 = detail::gc_make_rtree_iterators(geometry2, strategy);
0150 detail::visit_breadth_first([&](auto const& g1)
0151 {
0152 bool r = g1_prod_gc2(g1, rtree2, out, strategy);
0153 result = result || r;
0154 return true;
0155 }, geometry1);
0156
0157 detail::intersection::gc_move_multi_back(geometry_out, boost::get<0>(out));
0158 detail::intersection::gc_move_multi_back(geometry_out, boost::get<1>(out));
0159 detail::intersection::gc_move_multi_back(geometry_out, boost::get<2>(out));
0160
0161 return result;
0162 }
0163
0164 private:
0165
0166 template <typename G1, typename Rtree2, typename TupleOut, typename Strategy>
0167 static bool g1_prod_gc2(G1 const& g1, Rtree2 const& rtree2, TupleOut& out, Strategy const& strategy)
0168 {
0169 bool result = false;
0170
0171 using box1_t = detail::gc_make_rtree_box_t<G1>;
0172 box1_t b1 = geometry::return_envelope<box1_t>(g1, strategy);
0173 detail::expand_by_epsilon(b1);
0174
0175 for (auto qit = rtree2.qbegin(index::intersects(b1)); qit != rtree2.qend(); ++qit)
0176 {
0177 traits::iter_visit<Geometry2>::apply([&](auto const& g2)
0178 {
0179 TupleOut inters_result;
0180 using g2_t = util::remove_cref_t<decltype(g2)>;
0181 intersection<G1, g2_t, TupleOut>::apply(g1, g2, inters_result, strategy);
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 bool const r0 = intersection::template merge_result<0>(inters_result, out, strategy);
0192 bool const r1 = intersection::template merge_result<1>(inters_result, out, strategy);
0193 bool const r2 = intersection::template merge_result<2>(inters_result, out, strategy);
0194 result = result || r0 || r1 || r2;
0195 }, qit->second);
0196 }
0197
0198 return result;
0199 }
0200
0201 template <std::size_t Index, typename Out, typename Strategy>
0202 static bool merge_result(Out const& inters_result, Out& out, Strategy const& strategy)
0203 {
0204 auto const& multi_result = boost::get<Index>(inters_result);
0205 auto& multi_out = boost::get<Index>(out);
0206 if (! boost::empty(multi_result))
0207 {
0208 std::remove_reference_t<decltype(multi_out)> temp_result;
0209 merge_two(multi_out, multi_result, temp_result, strategy);
0210 multi_out = std::move(temp_result);
0211 return true;
0212 }
0213 return false;
0214 }
0215
0216 template <typename Out, typename Strategy, std::enable_if_t<! util::is_pointlike<Out>::value, int> = 0>
0217 static void merge_two(Out const& g1, Out const& g2, Out& out, Strategy const& strategy)
0218 {
0219 using rescale_policy_type = typename geometry::rescale_overlay_policy_type
0220 <
0221 Out, Out, typename Strategy::cs_tag
0222 >::type;
0223
0224 rescale_policy_type robust_policy
0225 = geometry::get_rescale_policy<rescale_policy_type>(
0226 g1, g2, strategy);
0227
0228 geometry::dispatch::intersection_insert
0229 <
0230 Out, Out, typename boost::range_value<Out>::type,
0231 overlay_union
0232 >::apply(g1,
0233 g2,
0234 robust_policy,
0235 geometry::range::back_inserter(out),
0236 strategy);
0237 }
0238
0239 template <typename Out, typename Strategy, std::enable_if_t<util::is_pointlike<Out>::value, int> = 0>
0240 static void merge_two(Out const& g1, Out const& g2, Out& out, Strategy const& strategy)
0241 {
0242 detail::overlay::union_pointlike_pointlike_point
0243 <
0244 Out, Out, typename boost::range_value<Out>::type
0245 >::apply(g1,
0246 g2,
0247 0,
0248 geometry::range::back_inserter(out),
0249 strategy);
0250 }
0251 };
0252
0253 template
0254 <
0255 typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1
0256 >
0257 struct intersection
0258 <
0259 Geometry1, Geometry2, GeometryOut,
0260 Tag1, geometry_collection_tag, geometry_collection_tag
0261 >
0262 {
0263 template <typename Strategy>
0264 static inline bool apply(Geometry1 const& geometry1,
0265 Geometry2 const& geometry2,
0266 GeometryOut& geometry_out,
0267 Strategy const& strategy)
0268 {
0269 using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
0270 return intersection
0271 <
0272 gc_view_t, Geometry2, GeometryOut
0273 >::apply(gc_view_t(geometry1), geometry2, geometry_out, strategy);
0274 }
0275 };
0276
0277 template
0278 <
0279 typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag2
0280 >
0281 struct intersection
0282 <
0283 Geometry1, Geometry2, GeometryOut,
0284 geometry_collection_tag, Tag2, geometry_collection_tag
0285 >
0286 {
0287 template <typename Strategy>
0288 static inline bool apply(Geometry1 const& geometry1,
0289 Geometry2 const& geometry2,
0290 GeometryOut& geometry_out,
0291 Strategy const& strategy)
0292 {
0293 using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
0294 return intersection
0295 <
0296 Geometry1, gc_view_t, GeometryOut
0297 >::apply(geometry1, gc_view_t(geometry2), geometry_out, strategy);
0298 }
0299 };
0300
0301 template
0302 <
0303 typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1, typename Tag2
0304 >
0305 struct intersection
0306 <
0307 Geometry1, Geometry2, GeometryOut,
0308 Tag1, Tag2, geometry_collection_tag
0309 >
0310 {
0311 template <typename Strategy>
0312 static inline bool apply(Geometry1 const& geometry1,
0313 Geometry2 const& geometry2,
0314 GeometryOut& geometry_out,
0315 Strategy const& strategy)
0316 {
0317 using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
0318 using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
0319 return intersection
0320 <
0321 gc1_view_t, gc2_view_t, GeometryOut
0322 >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), geometry_out, strategy);
0323 }
0324 };
0325
0326
0327 }
0328
0329 }}
0330
0331 #endif