Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/geometry/algorithms/union.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
0004 
0005 // This file was modified by Oracle on 2014-2024.
0006 // Modifications copyright (c) 2014-2024 Oracle and/or its affiliates.
0007 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0008 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0009 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0010 
0011 // Use, modification and distribution is subject to the Boost Software License,
0012 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0013 // http://www.boost.org/LICENSE_1_0.txt)
0014 
0015 #ifndef BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
0016 #define BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
0017 
0018 
0019 #include <boost/geometry/algorithms/detail/gc_group_elements.hpp>
0020 #include <boost/geometry/algorithms/detail/intersection/gc.hpp>
0021 #include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
0022 #include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
0023 #include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
0024 #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
0025 #include <boost/geometry/algorithms/not_implemented.hpp>
0026 #include <boost/geometry/core/point_order.hpp>
0027 #include <boost/geometry/core/primary_single_tag.hpp>
0028 #include <boost/geometry/core/reverse_dispatch.hpp>
0029 #include <boost/geometry/core/tag_cast.hpp>
0030 #include <boost/geometry/geometries/adapted/boost_variant.hpp>
0031 #include <boost/geometry/geometries/concepts/check.hpp>
0032 #include <boost/geometry/strategies/default_strategy.hpp>
0033 #include <boost/geometry/strategies/detail.hpp>
0034 #include <boost/geometry/strategies/relate/cartesian.hpp>
0035 #include <boost/geometry/strategies/relate/geographic.hpp>
0036 #include <boost/geometry/strategies/relate/spherical.hpp>
0037 #include <boost/geometry/util/type_traits_std.hpp>
0038 #include <boost/geometry/views/detail/geometry_collection_view.hpp>
0039 #include <boost/geometry/views/detail/random_access_view.hpp>
0040 
0041 
0042 namespace boost { namespace geometry
0043 {
0044 
0045 #ifndef DOXYGEN_NO_DISPATCH
0046 namespace dispatch
0047 {
0048 
0049 template
0050 <
0051     typename Geometry1, typename Geometry2, typename GeometryOut,
0052     typename TagIn1 = tag_t<Geometry1>,
0053     typename TagIn2 = tag_t<Geometry2>,
0054     typename TagOut = typename detail::setop_insert_output_tag<GeometryOut>::type,
0055     typename CastedTagIn1 = tag_cast_t<TagIn1, areal_tag, linear_tag, pointlike_tag>,
0056     typename CastedTagIn2 = tag_cast_t<TagIn2, areal_tag, linear_tag, pointlike_tag>,
0057     typename CastedTagOut = tag_cast_t<TagOut, areal_tag, linear_tag, pointlike_tag>,
0058     bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value
0059 >
0060 struct union_insert: not_implemented<TagIn1, TagIn2, TagOut>
0061 {};
0062 
0063 
0064 // If reversal is needed, perform it first
0065 
0066 template
0067 <
0068     typename Geometry1, typename Geometry2, typename GeometryOut,
0069     typename TagIn1, typename TagIn2, typename TagOut,
0070     typename CastedTagIn1, typename CastedTagIn2, typename CastedTagOut
0071 >
0072 struct union_insert
0073     <
0074         Geometry1, Geometry2, GeometryOut,
0075         TagIn1, TagIn2, TagOut,
0076         CastedTagIn1, CastedTagIn2, CastedTagOut,
0077         true
0078     >
0079 {
0080     template <typename OutputIterator, typename Strategy>
0081     static inline OutputIterator apply(Geometry1 const& g1,
0082                                        Geometry2 const& g2,
0083                                        OutputIterator out,
0084                                        Strategy const& strategy)
0085     {
0086         return union_insert
0087             <
0088                 Geometry2, Geometry1, GeometryOut
0089             >::apply(g2, g1, out, strategy);
0090     }
0091 };
0092 
0093 
0094 template
0095 <
0096     typename Geometry1, typename Geometry2, typename GeometryOut,
0097     typename TagIn1, typename TagIn2, typename TagOut
0098 >
0099 struct union_insert
0100     <
0101         Geometry1, Geometry2, GeometryOut,
0102         TagIn1, TagIn2, TagOut,
0103         areal_tag, areal_tag, areal_tag,
0104         false
0105     > : detail::overlay::overlay
0106         <
0107             Geometry1, Geometry2,
0108             detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
0109             detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
0110             detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
0111             GeometryOut,
0112             overlay_union
0113         >
0114 {};
0115 
0116 
0117 // dispatch for union of linear geometries
0118 template
0119 <
0120     typename Linear1, typename Linear2, typename LineStringOut,
0121     typename TagIn1, typename TagIn2
0122 >
0123 struct union_insert
0124     <
0125         Linear1, Linear2, LineStringOut,
0126         TagIn1, TagIn2, linestring_tag,
0127         linear_tag, linear_tag, linear_tag,
0128         false
0129     > : detail::overlay::linear_linear_linestring
0130         <
0131             Linear1, Linear2, LineStringOut, overlay_union
0132         >
0133 {};
0134 
0135 
0136 // dispatch for point-like geometries
0137 template
0138 <
0139     typename PointLike1, typename PointLike2, typename PointOut,
0140     typename TagIn1, typename TagIn2
0141 >
0142 struct union_insert
0143     <
0144         PointLike1, PointLike2, PointOut,
0145         TagIn1, TagIn2, point_tag,
0146         pointlike_tag, pointlike_tag, pointlike_tag,
0147         false
0148     > : detail::overlay::union_pointlike_pointlike_point
0149         <
0150             PointLike1, PointLike2, PointOut
0151         >
0152 {};
0153 
0154 
0155 template
0156 <
0157     typename Geometry1, typename Geometry2, typename SingleTupledOut,
0158     typename TagIn1, typename TagIn2,
0159     typename CastedTagIn
0160 >
0161 struct union_insert
0162     <
0163         Geometry1, Geometry2, SingleTupledOut,
0164         TagIn1, TagIn2, detail::tupled_output_tag,
0165         CastedTagIn, CastedTagIn, detail::tupled_output_tag,
0166         false
0167     >
0168 {
0169     using single_tag = primary_single_tag_t<CastedTagIn>;
0170 
0171     using expect_check = detail::expect_output
0172         <
0173             Geometry1, Geometry2, SingleTupledOut, single_tag
0174         >;
0175 
0176     using access = typename geometry::detail::output_geometry_access
0177         <
0178             SingleTupledOut, single_tag, single_tag
0179         >;
0180 
0181     template <typename OutputIterator, typename Strategy>
0182     static inline OutputIterator apply(Geometry1 const& g1,
0183                                        Geometry2 const& g2,
0184                                        OutputIterator out,
0185                                        Strategy const& strategy)
0186     {
0187         access::get(out) = union_insert
0188             <
0189                 Geometry2, Geometry1, typename access::type
0190             >::apply(g2, g1, access::get(out), strategy);
0191 
0192         return out;
0193     }
0194 };
0195 
0196 
0197 template
0198 <
0199     typename Geometry1, typename Geometry2, typename SingleTupledOut,
0200     typename SingleTag1, typename SingleTag2,
0201     bool Geometry1LesserTopoDim = (topological_dimension<Geometry1>::value
0202                                     < topological_dimension<Geometry2>::value)
0203 >
0204 struct union_insert_tupled_different
0205 {
0206     using access1 = typename geometry::detail::output_geometry_access
0207         <
0208             SingleTupledOut, SingleTag1, SingleTag1
0209         >;
0210 
0211     using access2 = typename geometry::detail::output_geometry_access
0212         <
0213             SingleTupledOut, SingleTag2, SingleTag2
0214         >;
0215 
0216     template <typename OutputIterator, typename Strategy>
0217     static inline OutputIterator apply(Geometry1 const& g1,
0218                                        Geometry2 const& g2,
0219                                        OutputIterator out,
0220                                        Strategy const& strategy)
0221     {
0222         access1::get(out) = geometry::dispatch::intersection_insert
0223             <
0224                 Geometry1, Geometry2,
0225                 typename access1::type,
0226                 overlay_difference,
0227                 geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
0228                 geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
0229             >::apply(g1, g2, access1::get(out), strategy);
0230 
0231         access2::get(out) = geometry::detail::convert_to_output
0232             <
0233                 Geometry2,
0234                 typename access2::type
0235             >::apply(g2, access2::get(out));
0236 
0237         return out;
0238     }
0239 };
0240 
0241 
0242 template
0243 <
0244     typename Geometry1, typename Geometry2, typename SingleTupledOut,
0245     typename SingleTag1, typename SingleTag2
0246 >
0247 struct union_insert_tupled_different
0248     <
0249         Geometry1, Geometry2, SingleTupledOut, SingleTag1, SingleTag2, false
0250     >
0251 {
0252     template <typename OutputIterator, typename Strategy>
0253     static inline OutputIterator apply(Geometry1 const& g1,
0254                                        Geometry2 const& g2,
0255                                        OutputIterator out,
0256                                        Strategy const& strategy)
0257     {
0258         return union_insert_tupled_different
0259             <
0260                 Geometry2, Geometry1, SingleTupledOut, SingleTag2, SingleTag1, true
0261             >::apply(g2, g1, out, strategy);
0262     }
0263 };
0264 
0265 
0266 template
0267 <
0268     typename Geometry1, typename Geometry2, typename SingleTupledOut,
0269     typename TagIn1, typename TagIn2,
0270     typename CastedTagIn1, typename CastedTagIn2
0271 >
0272 struct union_insert
0273     <
0274         Geometry1, Geometry2, SingleTupledOut,
0275         TagIn1, TagIn2, detail::tupled_output_tag,
0276         CastedTagIn1, CastedTagIn2, detail::tupled_output_tag,
0277         false
0278     >
0279 {
0280     using single_tag1 = primary_single_tag_t<CastedTagIn1>;
0281 
0282     using expect_check1 = detail::expect_output
0283         <
0284             Geometry1, Geometry2, SingleTupledOut, single_tag1
0285         >;
0286 
0287     using single_tag2 = primary_single_tag_t<CastedTagIn2>;
0288 
0289     using expect_check2 = detail::expect_output
0290         <
0291             Geometry1, Geometry2, SingleTupledOut, single_tag2
0292         >;
0293 
0294     template <typename OutputIterator, typename Strategy>
0295     static inline OutputIterator apply(Geometry1 const& g1,
0296                                        Geometry2 const& g2,
0297                                        OutputIterator out,
0298                                        Strategy const& strategy)
0299     {
0300         return union_insert_tupled_different
0301             <
0302                 Geometry1, Geometry2, SingleTupledOut, single_tag1, single_tag2
0303             >::apply(g1, g2, out, strategy);
0304     }
0305 };
0306 
0307 
0308 } // namespace dispatch
0309 #endif // DOXYGEN_NO_DISPATCH
0310 
0311 #ifndef DOXYGEN_NO_DETAIL
0312 namespace detail { namespace union_
0313 {
0314 
0315 /*!
0316 \brief_calc2{union}
0317 \ingroup union
0318 \details \details_calc2{union_insert, spatial set theoretic union}.
0319     \details_insert{union}
0320 \tparam GeometryOut output geometry type, must be specified
0321 \tparam Geometry1 \tparam_geometry
0322 \tparam Geometry2 \tparam_geometry
0323 \tparam OutputIterator output iterator
0324 \param geometry1 \param_geometry
0325 \param geometry2 \param_geometry
0326 \param out \param_out{union}
0327 \return \return_out
0328 */
0329 template
0330 <
0331     typename GeometryOut,
0332     typename Geometry1,
0333     typename Geometry2,
0334     typename OutputIterator
0335 >
0336 inline OutputIterator union_insert(Geometry1 const& geometry1,
0337             Geometry2 const& geometry2,
0338             OutputIterator out)
0339 {
0340     concepts::check<Geometry1 const>();
0341     concepts::check<Geometry2 const>();
0342     geometry::detail::output_geometry_concept_check<GeometryOut>::apply();
0343 
0344     typename strategies::relate::services::default_strategy
0345         <
0346             Geometry1, Geometry2
0347         >::type strategy;
0348 
0349     return dispatch::union_insert
0350            <
0351                Geometry1, Geometry2, GeometryOut
0352            >::apply(geometry1, geometry2, out, strategy);
0353 }
0354 
0355 
0356 }} // namespace detail::union_
0357 #endif // DOXYGEN_NO_DETAIL
0358 
0359 
0360 namespace resolve_collection
0361 {
0362 
0363 template
0364 <
0365     typename Geometry1, typename Geometry2, typename GeometryOut,
0366     typename Tag1 = geometry::tag_t<Geometry1>,
0367     typename Tag2 = geometry::tag_t<Geometry2>,
0368     typename TagOut = geometry::tag_t<GeometryOut>
0369 >
0370 struct union_
0371 {
0372     template <typename Strategy>
0373     static void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
0374                       GeometryOut & geometry_out, Strategy const& strategy)
0375     {
0376         using single_out = typename geometry::detail::output_geometry_value
0377             <
0378                 GeometryOut
0379             >::type;
0380 
0381         dispatch::union_insert
0382            <
0383                Geometry1, Geometry2, single_out
0384            >::apply(geometry1, geometry2,
0385                     geometry::detail::output_geometry_back_inserter(geometry_out),
0386                     strategy);
0387     }
0388 };
0389 
0390 template
0391 <
0392     typename Geometry1, typename Geometry2, typename GeometryOut
0393 >
0394 struct union_
0395     <
0396         Geometry1, Geometry2, GeometryOut,
0397         geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
0398     >
0399 {
0400     // NOTE: for now require all of the possible output types
0401     //       technically only a subset could be needed.
0402     using multi_point_t = typename util::sequence_find_if
0403         <
0404             typename traits::geometry_types<GeometryOut>::type,
0405             util::is_multi_point
0406         >::type;
0407     using multi_linestring_t = typename util::sequence_find_if
0408         <
0409             typename traits::geometry_types<GeometryOut>::type,
0410             util::is_multi_linestring
0411         >::type;
0412     using multi_polygon_t = typename util::sequence_find_if
0413         <
0414             typename traits::geometry_types<GeometryOut>::type,
0415             util::is_multi_polygon
0416         >::type;
0417     using tuple_out_t = boost::tuple<multi_point_t, multi_linestring_t, multi_polygon_t>;
0418 
0419     template <typename Strategy>
0420     static inline void apply(Geometry1 const& geometry1,
0421                              Geometry2 const& geometry2,
0422                              GeometryOut& geometry_out,
0423                              Strategy const& strategy)
0424     {
0425         detail::random_access_view<Geometry1 const> gc1_view(geometry1);
0426         detail::random_access_view<Geometry2 const> gc2_view(geometry2);
0427 
0428         detail::gc_group_elements(gc1_view, gc2_view, strategy,
0429             [&](auto const& inters_group)
0430             {
0431                 tuple_out_t out;
0432                 merge_group(gc1_view, gc2_view, strategy, inters_group, out);
0433                 detail::intersection::gc_move_multi_back(geometry_out, boost::get<0>(out));
0434                 detail::intersection::gc_move_multi_back(geometry_out, boost::get<1>(out));
0435                 detail::intersection::gc_move_multi_back(geometry_out, boost::get<2>(out));
0436                 return true;
0437             },
0438             [&](auto const& disjoint_group)
0439             {
0440                 copy_disjoint(gc1_view, gc2_view, disjoint_group, geometry_out);
0441             });
0442     }
0443 
0444 private:
0445     template <typename GC1View, typename GC2View, typename Strategy, typename Group>
0446     static inline void merge_group(GC1View const& gc1_view, GC2View const& gc2_view,
0447                                    Strategy const& strategy, Group const& inters_group,
0448                                    tuple_out_t& out)
0449     {
0450         for (auto const& id : inters_group)
0451         {
0452             if (id.source_id == 0)
0453             {
0454                 traits::iter_visit<GC1View>::apply([&](auto const& g1)
0455                 {
0456                     merge_one(out, g1, strategy);
0457                 }, boost::begin(gc1_view) + id.gc_id);
0458             }
0459             else
0460             {
0461                 traits::iter_visit<GC2View>::apply([&](auto const& g2)
0462                 {
0463                     merge_one(out, g2, strategy);
0464                 }, boost::begin(gc2_view) + id.gc_id);
0465             }
0466         }
0467         /*
0468         // L = L \ A
0469         {
0470             multi_linestring_t l;
0471             subtract_greater_topodim(boost::get<1>(out), boost::get<2>(out), l, strategy);
0472             boost::get<1>(out) = std::move(l);
0473         }
0474         // P = P \ A
0475         {
0476             multi_point_t p;
0477             subtract_greater_topodim(boost::get<0>(out), boost::get<2>(out), p, strategy);
0478             boost::get<0>(out) = std::move(p);
0479         }
0480         // P = P \ L
0481         {
0482             multi_point_t p;
0483             subtract_greater_topodim(boost::get<0>(out), boost::get<1>(out), p, strategy);
0484             boost::get<0>(out) = std::move(p);
0485         }
0486         */
0487     }
0488 
0489     template <typename G, typename Strategy, std::enable_if_t<util::is_pointlike<G>::value, int> = 0>
0490     static inline void merge_one(tuple_out_t& out, G const& g, Strategy const& strategy)
0491     {
0492         multi_point_t p;
0493         union_<multi_point_t, G, multi_point_t>::apply(boost::get<0>(out), g, p, strategy);
0494         boost::get<0>(out) = std::move(p);
0495     }
0496 
0497     template <typename G, typename Strategy, std::enable_if_t<util::is_linear<G>::value, int> = 0>
0498     static inline void merge_one(tuple_out_t& out, G const& g, Strategy const& strategy)
0499     {
0500         multi_linestring_t l;
0501         union_<multi_linestring_t, G, multi_linestring_t>::apply(boost::get<1>(out), g, l, strategy);
0502         boost::get<1>(out) = std::move(l);
0503     }
0504 
0505     template <typename G, typename Strategy, std::enable_if_t<util::is_areal<G>::value, int> = 0>
0506     static inline void merge_one(tuple_out_t& out, G const& g, Strategy const& strategy)
0507     {
0508         multi_polygon_t a;
0509         union_<multi_polygon_t, G, multi_polygon_t>::apply(boost::get<2>(out), g, a, strategy);
0510         boost::get<2>(out) = std::move(a);
0511     }
0512 
0513     template <typename GC1View, typename GC2View, typename Group>
0514     static inline void copy_disjoint(GC1View const& gc1_view, GC2View const& gc2_view,
0515                                      Group const& disjoint_group, GeometryOut& geometry_out)
0516     {
0517         for (auto const& id : disjoint_group)
0518         {
0519             if (id.source_id == 0)
0520             {
0521                 traits::iter_visit<GC1View>::apply([&](auto const& g1)
0522                 {
0523                     copy_one(g1, geometry_out);
0524                 }, boost::begin(gc1_view) + id.gc_id);
0525             }
0526             else
0527             {
0528                 traits::iter_visit<GC2View>::apply([&](auto const& g2)
0529                 {
0530                     copy_one(g2, geometry_out);
0531                 }, boost::begin(gc2_view) + id.gc_id);
0532             }
0533         }
0534     }
0535 
0536     template <typename G, std::enable_if_t<util::is_pointlike<G>::value, int> = 0>
0537     static inline void copy_one(G const& g, GeometryOut& geometry_out)
0538     {
0539         multi_point_t p;
0540         geometry::convert(g, p);
0541         detail::intersection::gc_move_multi_back(geometry_out, p);
0542     }
0543 
0544     template <typename G, std::enable_if_t<util::is_linear<G>::value, int> = 0>
0545     static inline void copy_one(G const& g, GeometryOut& geometry_out)
0546     {
0547         multi_linestring_t l;
0548         geometry::convert(g, l);
0549         detail::intersection::gc_move_multi_back(geometry_out, l);
0550     }
0551 
0552     template <typename G, std::enable_if_t<util::is_areal<G>::value, int> = 0>
0553     static inline void copy_one(G const& g, GeometryOut& geometry_out)
0554     {
0555         multi_polygon_t a;
0556         geometry::convert(g, a);
0557         detail::intersection::gc_move_multi_back(geometry_out, a);
0558     }
0559     /*
0560     template <typename Multi1, typename Multi2, typename Strategy>
0561     static inline void subtract_greater_topodim(Multi1 const& multi1, Multi2 const& multi2, Multi1& multi_out, Strategy const& strategy)
0562     {
0563         geometry::dispatch::intersection_insert
0564             <
0565                 Multi1, Multi2,
0566                 typename boost::range_value<Multi1>::type,
0567                 overlay_difference,
0568                 geometry::detail::overlay::do_reverse<geometry::point_order<Multi1>::value>::value,
0569                 geometry::detail::overlay::do_reverse<geometry::point_order<Multi2>::value, true>::value
0570             >::apply(multi1, multi2, range::back_inserter(multi_out), strategy);
0571     }
0572     */
0573 };
0574 
0575 template
0576 <
0577     typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1
0578 >
0579 struct union_
0580     <
0581         Geometry1, Geometry2, GeometryOut,
0582         Tag1, geometry_collection_tag, geometry_collection_tag
0583     >
0584 {
0585     template <typename Strategy>
0586     static inline void apply(Geometry1 const& geometry1,
0587                              Geometry2 const& geometry2,
0588                              GeometryOut& geometry_out,
0589                              Strategy const& strategy)
0590     {
0591         using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
0592         union_
0593             <
0594                 gc_view_t, Geometry2, GeometryOut
0595             >::apply(gc_view_t(geometry1), geometry2, geometry_out, strategy);
0596     }
0597 };
0598 
0599 template
0600 <
0601     typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag2
0602 >
0603 struct union_
0604     <
0605         Geometry1, Geometry2, GeometryOut,
0606         geometry_collection_tag, Tag2, geometry_collection_tag
0607     >
0608 {
0609     template <typename Strategy>
0610     static inline void apply(Geometry1 const& geometry1,
0611                              Geometry2 const& geometry2,
0612                              GeometryOut& geometry_out,
0613                              Strategy const& strategy)
0614     {
0615         using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
0616         union_
0617             <
0618                 Geometry1, gc_view_t, GeometryOut
0619             >::apply(geometry1, gc_view_t(geometry2), geometry_out, strategy);
0620     }
0621 };
0622 
0623 template
0624 <
0625     typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1, typename Tag2
0626 >
0627 struct union_
0628     <
0629         Geometry1, Geometry2, GeometryOut,
0630         Tag1, Tag2, geometry_collection_tag
0631     >
0632 {
0633     template <typename Strategy>
0634     static inline void apply(Geometry1 const& geometry1,
0635                              Geometry2 const& geometry2,
0636                              GeometryOut& geometry_out,
0637                              Strategy const& strategy)
0638     {
0639         using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
0640         using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
0641         union_
0642             <
0643                 gc1_view_t, gc2_view_t, GeometryOut
0644             >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), geometry_out, strategy);
0645     }
0646 };
0647 
0648 } // namespace resolve_collection
0649 
0650 
0651 namespace resolve_strategy {
0652 
0653 template
0654 <
0655     typename Strategy,
0656     bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
0657 >
0658 struct union_
0659 {
0660     template <typename Geometry1, typename Geometry2, typename Collection>
0661     static inline void apply(Geometry1 const& geometry1,
0662                              Geometry2 const& geometry2,
0663                              Collection & output_collection,
0664                              Strategy const& strategy)
0665     {
0666         resolve_collection::union_
0667             <
0668                 Geometry1, Geometry2, Collection
0669             >::apply(geometry1, geometry2, output_collection, strategy);
0670     }
0671 };
0672 
0673 template <typename Strategy>
0674 struct union_<Strategy, false>
0675 {
0676     template <typename Geometry1, typename Geometry2, typename Collection>
0677     static inline void apply(Geometry1 const& geometry1,
0678                              Geometry2 const& geometry2,
0679                              Collection & output_collection,
0680                              Strategy const& strategy)
0681     {
0682         using strategies::relate::services::strategy_converter;
0683 
0684         union_
0685             <
0686                 decltype(strategy_converter<Strategy>::get(strategy))
0687             >::apply(geometry1, geometry2, output_collection,
0688                      strategy_converter<Strategy>::get(strategy));
0689     }
0690 };
0691 
0692 template <>
0693 struct union_<default_strategy, false>
0694 {
0695     template <typename Geometry1, typename Geometry2, typename Collection>
0696     static inline void apply(Geometry1 const& geometry1,
0697                              Geometry2 const& geometry2,
0698                              Collection & output_collection,
0699                              default_strategy)
0700     {
0701         using strategy_type = typename strategies::relate::services::default_strategy
0702             <
0703                 Geometry1,
0704                 Geometry2
0705             >::type;
0706 
0707         union_
0708             <
0709                 strategy_type
0710             >::apply(geometry1, geometry2, output_collection, strategy_type());
0711     }
0712 };
0713 
0714 } // resolve_strategy
0715 
0716 
0717 namespace resolve_dynamic
0718 {
0719 
0720 template
0721 <
0722     typename Geometry1, typename Geometry2,
0723     typename Tag1 = geometry::tag_t<Geometry1>,
0724     typename Tag2 = geometry::tag_t<Geometry2>
0725 >
0726 struct union_
0727 {
0728     template <typename Collection, typename Strategy>
0729     static inline void apply(Geometry1 const& geometry1,
0730                              Geometry2 const& geometry2,
0731                              Collection& output_collection,
0732                              Strategy const& strategy)
0733     {
0734         concepts::check<Geometry1 const>();
0735         concepts::check<Geometry2 const>();
0736         //concepts::check<typename boost::range_value<Collection>::type>();
0737         geometry::detail::output_geometry_concept_check
0738             <
0739                 typename geometry::detail::output_geometry_value
0740                     <
0741                         Collection
0742                     >::type
0743             >::apply();
0744 
0745         resolve_strategy::union_
0746             <
0747                 Strategy
0748             >::apply(geometry1, geometry2, output_collection, strategy);
0749     }
0750 };
0751 
0752 
0753 template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
0754 struct union_<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
0755 {
0756     template <typename Collection, typename Strategy>
0757     static inline void apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
0758                              Collection& output_collection, Strategy const& strategy)
0759     {
0760         traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
0761         {
0762             union_
0763                 <
0764                     util::remove_cref_t<decltype(g1)>,
0765                     Geometry2
0766                 >::apply(g1, geometry2, output_collection, strategy);
0767         }, geometry1);
0768     }
0769 };
0770 
0771 
0772 template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
0773 struct union_<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
0774 {
0775     template <typename Collection, typename Strategy>
0776     static inline void apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
0777                              Collection& output_collection, Strategy const& strategy)
0778     {
0779         traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
0780         {
0781             union_
0782                 <
0783                     Geometry1,
0784                     util::remove_cref_t<decltype(g2)>
0785                 >::apply(geometry1, g2, output_collection, strategy);
0786         }, geometry2);
0787     }
0788 };
0789 
0790 
0791 template <typename DynamicGeometry1, typename DynamicGeometry2>
0792 struct union_<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
0793 {
0794     template <typename Collection, typename Strategy>
0795     static inline void apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
0796                              Collection& output_collection, Strategy const& strategy)
0797     {
0798         traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
0799         {
0800             union_
0801                 <
0802                     util::remove_cref_t<decltype(g1)>,
0803                     util::remove_cref_t<decltype(g2)>
0804                 >::apply(g1, g2, output_collection, strategy);
0805         }, geometry1, geometry2);
0806     }
0807 };
0808 
0809 
0810 } // namespace resolve_dynamic
0811 
0812 
0813 /*!
0814 \brief Combines two geometries which each other
0815 \ingroup union
0816 \details \details_calc2{union, spatial set theoretic union}.
0817 \tparam Geometry1 \tparam_geometry
0818 \tparam Geometry2 \tparam_geometry
0819 \tparam Collection output collection, either a multi-geometry,
0820     or a std::vector<Geometry> / std::deque<Geometry> etc
0821 \tparam Strategy \tparam_strategy{Union_}
0822 \param geometry1 \param_geometry
0823 \param geometry2 \param_geometry
0824 \param output_collection the output collection
0825 \param strategy \param_strategy{union_}
0826 \note Called union_ because union is a reserved word.
0827 
0828 \qbk{distinguish,with strategy}
0829 \qbk{[include reference/algorithms/union.qbk]}
0830 */
0831 template
0832 <
0833     typename Geometry1,
0834     typename Geometry2,
0835     typename Collection,
0836     typename Strategy
0837 >
0838 inline void union_(Geometry1 const& geometry1,
0839                    Geometry2 const& geometry2,
0840                    Collection& output_collection,
0841                    Strategy const& strategy)
0842 {
0843     resolve_dynamic::union_
0844         <
0845             Geometry1,
0846             Geometry2
0847         >::apply(geometry1, geometry2, output_collection, strategy);
0848 }
0849 
0850 
0851 /*!
0852 \brief Combines two geometries which each other
0853 \ingroup union
0854 \details \details_calc2{union, spatial set theoretic union}.
0855 \tparam Geometry1 \tparam_geometry
0856 \tparam Geometry2 \tparam_geometry
0857 \tparam Collection output collection, either a multi-geometry,
0858     or a std::vector<Geometry> / std::deque<Geometry> etc
0859 \param geometry1 \param_geometry
0860 \param geometry2 \param_geometry
0861 \param output_collection the output collection
0862 \note Called union_ because union is a reserved word.
0863 
0864 \qbk{[include reference/algorithms/union.qbk]}
0865 */
0866 template
0867 <
0868     typename Geometry1,
0869     typename Geometry2,
0870     typename Collection
0871 >
0872 inline void union_(Geometry1 const& geometry1,
0873                    Geometry2 const& geometry2,
0874                    Collection& output_collection)
0875 {
0876     resolve_dynamic::union_
0877         <
0878             Geometry1,
0879             Geometry2
0880         >::apply(geometry1, geometry2, output_collection, default_strategy());
0881 }
0882 
0883 
0884 }} // namespace boost::geometry
0885 
0886 
0887 #endif // BOOST_GEOMETRY_ALGORITHMS_UNION_HPP