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