Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:42:51

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2007-2015 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 
0008 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0009 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0010 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0011 
0012 // Use, modification and distribution is subject to the Boost Software License,
0013 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0014 // http://www.boost.org/LICENSE_1_0.txt)
0015 
0016 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP
0017 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP
0018 
0019 
0020 #include <cstddef>
0021 #include <deque>
0022 #include <type_traits>
0023 
0024 #include <boost/range/begin.hpp>
0025 #include <boost/range/end.hpp>
0026 #include <boost/range/size.hpp>
0027 
0028 #include <boost/geometry/algorithms/convert.hpp>
0029 #include <boost/geometry/algorithms/detail/point_on_border.hpp>
0030 #include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp>
0031 #include <boost/geometry/algorithms/detail/overlay/follow.hpp>
0032 #include <boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp>
0033 #include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
0034 #include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
0035 #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
0036 #include <boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp>
0037 #include <boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp>
0038 #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
0039 #include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
0040 #include <boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp>
0041 
0042 #include <boost/geometry/core/point_order.hpp>
0043 #include <boost/geometry/core/reverse_dispatch.hpp>
0044 #include <boost/geometry/core/static_assert.hpp>
0045 #include <boost/geometry/core/tag_cast.hpp>
0046 
0047 #include <boost/geometry/geometries/concepts/check.hpp>
0048 
0049 #include <boost/geometry/strategies/default_strategy.hpp>
0050 #include <boost/geometry/strategies/detail.hpp>
0051 #include <boost/geometry/strategies/relate/services.hpp>
0052 
0053 #include <boost/geometry/views/segment_view.hpp>
0054 #include <boost/geometry/views/detail/boundary_view.hpp>
0055 
0056 #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
0057 #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
0058 #include <boost/geometry/io/wkt/wkt.hpp>
0059 #include <boost/geometry/views/enumerate_view.hpp>
0060 #endif
0061 
0062 namespace boost { namespace geometry
0063 {
0064 
0065 #ifndef DOXYGEN_NO_DETAIL
0066 namespace detail { namespace intersection
0067 {
0068 
0069 template <typename PointOut>
0070 struct intersection_segment_segment_point
0071 {
0072     template
0073     <
0074         typename Segment1, typename Segment2,
0075         typename OutputIterator, typename Strategy
0076     >
0077     static inline OutputIterator apply(Segment1 const& segment1,
0078             Segment2 const& segment2,
0079             OutputIterator out,
0080             Strategy const& strategy)
0081     {
0082         using point_type = point_type_t<PointOut>;
0083         using intersection_return_type = segment_intersection_points<point_type>;
0084         using policy_type = policies::relate::segments_intersection_points
0085             <
0086                 intersection_return_type
0087             >;
0088 
0089         // Get the intersection point (or two points)
0090         detail::segment_as_subrange<Segment1> sub_range1(segment1);
0091         detail::segment_as_subrange<Segment2> sub_range2(segment2);
0092 
0093         intersection_return_type
0094             is = strategy.relate().apply(sub_range1, sub_range2, policy_type());
0095 
0096         for (std::size_t i = 0; i < is.count; i++)
0097         {
0098             PointOut p;
0099             geometry::convert(is.intersections[i], p);
0100             *out++ = p;
0101         }
0102         return out;
0103     }
0104 };
0105 
0106 template <typename PointOut>
0107 struct intersection_linestring_linestring_point
0108 {
0109     template
0110     <
0111         typename Linestring1, typename Linestring2,
0112         typename OutputIterator,
0113         typename Strategy
0114     >
0115     static inline OutputIterator apply(Linestring1 const& linestring1,
0116             Linestring2 const& linestring2,
0117             OutputIterator out,
0118             Strategy const& strategy)
0119     {
0120         using turn_info = detail::overlay::turn_info<PointOut>;
0121         std::deque<turn_info> turns;
0122 
0123         geometry::get_intersection_points(linestring1, linestring2,
0124                                           turns, strategy);
0125 
0126         for (auto const& turn : turns)
0127         {
0128             PointOut p;
0129             geometry::convert(turn.point, p);
0130             *out++ = p;
0131         }
0132         return out;
0133     }
0134 };
0135 
0136 /*!
0137 \brief Version of linestring with an areal feature (polygon or multipolygon)
0138 */
0139 template
0140 <
0141     bool ReverseAreal,
0142     typename GeometryOut,
0143     overlay_type OverlayType,
0144     bool FollowIsolatedPoints
0145 >
0146 struct intersection_of_linestring_with_areal
0147 {
0148 #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
0149     template <typename Turn, typename Operation>
0150     static inline void debug_follow(Turn const& turn, Operation op,
0151                                     int index)
0152     {
0153         std::cout << index
0154                   << " at " << op.seg_id
0155                   << " meth: " << method_char(turn.method)
0156                   << " op: " << operation_char(op.operation)
0157                   << " vis: " << visited_char(op.visited)
0158                   << " of:  " << operation_char(turn.operations[0].operation)
0159                   << operation_char(turn.operations[1].operation)
0160                   << " " << geometry::wkt(turn.point)
0161                   << std::endl;
0162     }
0163 
0164     template <typename Turn>
0165     static inline void debug_turn(Turn const& t, bool non_crossing)
0166     {
0167         std::cout << "checking turn @"
0168                   << geometry::wkt(t.point)
0169                   << "; " << method_char(t.method)
0170                   << ":" << operation_char(t.operations[0].operation)
0171                   << "/" << operation_char(t.operations[1].operation)
0172                   << "; non-crossing? "
0173                   << std::boolalpha << non_crossing << std::noboolalpha
0174                   << std::endl;
0175     }
0176 #endif
0177 
0178     template <typename Linestring, typename Areal, typename Strategy, typename Turns>
0179     static inline bool simple_turns_analysis(Linestring const& linestring,
0180                                              Areal const& areal,
0181                                              Strategy const& strategy,
0182                                              Turns const& turns,
0183                                              int & inside_value)
0184     {
0185         using namespace overlay;
0186 
0187         bool found_continue = false;
0188         bool found_intersection = false;
0189         bool found_union = false;
0190         bool found_front = false;
0191 
0192         for (auto const& turn : turns)
0193         {
0194             method_type const method = turn.method;
0195             operation_type const op = turn.operations[0].operation;
0196 
0197             if (method == method_crosses)
0198             {
0199                 return false;
0200             }
0201             else if (op == operation_intersection)
0202             {
0203                 found_intersection = true;
0204             }
0205             else if (op == operation_union)
0206             {
0207                 found_union = true;
0208             }
0209             else if (op == operation_continue)
0210             {
0211                 found_continue = true;
0212             }
0213 
0214             if ((found_intersection || found_continue) && found_union)
0215             {
0216                 return false;
0217             }
0218 
0219             if (turn.operations[0].position == position_front)
0220             {
0221                 found_front = true;
0222             }
0223         }
0224 
0225         if (found_front)
0226         {
0227             if (found_intersection)
0228             {
0229                 inside_value = 1; // inside
0230             }
0231             else if (found_union)
0232             {
0233                 inside_value = -1; // outside
0234             }
0235             else // continue and blocked
0236             {
0237                 inside_value = 0;
0238             }
0239             return true;
0240         }
0241 
0242         // if needed analyse points of a linestring
0243         // NOTE: range_in_geometry checks points of a linestring
0244         // until a point inside/outside areal is found
0245         // TODO: Could be replaced with point_in_geometry() because found_front is false
0246         inside_value = range_in_geometry(linestring, areal, strategy);
0247 
0248         if ( (found_intersection && inside_value == -1) // going in from outside
0249           || (found_continue && inside_value == -1) // going on boundary from outside
0250           || (found_union && inside_value == 1) ) // going out from inside
0251         {
0252             return false;
0253         }
0254 
0255         return true;
0256     }
0257 
0258     template
0259     <
0260         typename LineString, typename Areal,
0261         typename OutputIterator, typename Strategy
0262     >
0263     static inline OutputIterator apply(LineString const& linestring, Areal const& areal,
0264             OutputIterator out,
0265             Strategy const& strategy)
0266     {
0267         if (boost::size(linestring) == 0)
0268         {
0269             return out;
0270         }
0271 
0272         using follower = detail::overlay::follow
0273                 <
0274                     GeometryOut,
0275                     LineString,
0276                     Areal,
0277                     OverlayType,
0278                     false, // do not remove spikes for linear geometries
0279                     FollowIsolatedPoints
0280                 >;
0281 
0282         using linear = typename geometry::detail::output_geometry_access
0283             <
0284                 GeometryOut, linestring_tag, linestring_tag
0285             >;
0286 
0287         using point_type = point_type_t<typename linear::type>;
0288 
0289         using ratio_type = geometry::segment_ratio
0290             <
0291                 coordinate_type_t<point_type>
0292             >;
0293 
0294         using turn_info = detail::overlay::turn_info
0295             <
0296                 point_type,
0297                 ratio_type,
0298                 detail::overlay::turn_operation_linear
0299                     <
0300                         point_type,
0301                         ratio_type
0302                     >
0303             >;
0304 
0305         std::deque<turn_info> turns;
0306 
0307         detail::get_turns::no_interrupt_policy policy;
0308 
0309         using turn_policy = detail::overlay::get_turn_info_linear_areal
0310             <
0311                 detail::overlay::assign_null_policy
0312             >;
0313 
0314         dispatch::get_turns
0315             <
0316                 geometry::tag_t<LineString>,
0317                 geometry::tag_t<Areal>,
0318                 LineString,
0319                 Areal,
0320                 false,
0321                 (OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),
0322                 turn_policy
0323             >::apply(0, linestring, 1, areal,
0324                      strategy,
0325                      turns, policy);
0326 
0327         int inside_value = 0;
0328         if (simple_turns_analysis(linestring, areal, strategy, turns, inside_value))
0329         {
0330             // No crossing the boundary, it is either
0331             // inside (interior + borders)
0332             // or outside (exterior + borders)
0333             // or on boundary
0334 
0335             // add linestring to the output if conditions are met
0336             if (follower::included(inside_value))
0337             {
0338                 typename linear::type copy;
0339                 geometry::convert(linestring, copy);
0340                 *linear::get(out)++ = copy;
0341             }
0342 
0343             return out;
0344         }
0345 
0346 #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
0347         for (auto const& item : util::enumerate(turns))
0348         {
0349             auto const& turn = item.value;
0350             debug_follow(turn, turn.operations[0], item.index);
0351         }
0352 #endif
0353 
0354         return follower::apply
0355                 (
0356                     linestring, areal,
0357                     geometry::detail::overlay::operation_intersection,
0358                     turns, out, strategy
0359                 );
0360     }
0361 };
0362 
0363 
0364 template <typename Turns, typename OutputIterator>
0365 inline OutputIterator intersection_output_turn_points(Turns const& turns,
0366                                                       OutputIterator out)
0367 {
0368     for (auto const& turn : turns)
0369     {
0370         *out++ = turn.point;
0371     }
0372 
0373     return out;
0374 }
0375 
0376 template <typename PointOut>
0377 struct intersection_areal_areal_point
0378 {
0379     template
0380     <
0381         typename Geometry1, typename Geometry2,
0382         typename OutputIterator,
0383         typename Strategy
0384     >
0385     static inline OutputIterator apply(Geometry1 const& geometry1,
0386                                        Geometry2 const& geometry2,
0387                                        OutputIterator out,
0388                                        Strategy const& strategy)
0389     {
0390         using turn_info = detail::overlay::turn_info
0391             <
0392                 PointOut,
0393                 typename segment_ratio_type<PointOut>::type
0394             >;
0395         std::vector<turn_info> turns;
0396 
0397         detail::get_turns::no_interrupt_policy policy;
0398 
0399         geometry::get_turns
0400             <
0401                 false, false, detail::overlay::assign_null_policy
0402             >(geometry1, geometry2, strategy, turns, policy);
0403 
0404         return intersection_output_turn_points(turns, out);
0405     }
0406 };
0407 
0408 template <typename PointOut>
0409 struct intersection_linear_areal_point
0410 {
0411     template
0412     <
0413         typename Geometry1, typename Geometry2,
0414         typename OutputIterator,
0415         typename Strategy
0416     >
0417     static inline OutputIterator apply(Geometry1 const& geometry1,
0418                                        Geometry2 const& geometry2,
0419                                        OutputIterator out,
0420                                        Strategy const& strategy)
0421     {
0422         using ratio_type = geometry::segment_ratio<geometry::coordinate_type_t<PointOut>>;
0423 
0424         using turn_info = detail::overlay::turn_info
0425             <
0426                 PointOut,
0427                 ratio_type,
0428                 detail::overlay::turn_operation_linear
0429                     <
0430                         PointOut,
0431                         ratio_type
0432                     >
0433             >;
0434 
0435         using turn_policy = detail::overlay::get_turn_info_linear_areal
0436             <
0437                 detail::overlay::assign_null_policy
0438             >;
0439 
0440         std::vector<turn_info> turns;
0441 
0442         detail::get_turns::no_interrupt_policy interrupt_policy;
0443 
0444         dispatch::get_turns
0445             <
0446                 geometry::tag_t<Geometry1>,
0447                 geometry::tag_t<Geometry2>,
0448                 Geometry1,
0449                 Geometry2,
0450                 false,
0451                 false,
0452                 turn_policy
0453             >::apply(0, geometry1, 1, geometry2,
0454                      strategy,
0455                      turns, interrupt_policy);
0456 
0457         return intersection_output_turn_points(turns, out);
0458     }
0459 };
0460 
0461 template <typename PointOut>
0462 struct intersection_areal_linear_point
0463 {
0464     template
0465     <
0466         typename Geometry1, typename Geometry2,
0467         typename OutputIterator,
0468         typename Strategy
0469     >
0470     static inline OutputIterator apply(Geometry1 const& geometry1,
0471                                        Geometry2 const& geometry2,
0472                                        OutputIterator out,
0473                                        Strategy const& strategy)
0474     {
0475         return intersection_linear_areal_point
0476             <
0477                 PointOut
0478             >::apply(geometry2, geometry1, out, strategy);
0479     }
0480 };
0481 
0482 
0483 }} // namespace detail::intersection
0484 #endif // DOXYGEN_NO_DETAIL
0485 
0486 
0487 
0488 #ifndef DOXYGEN_NO_DISPATCH
0489 namespace dispatch
0490 {
0491 
0492 template
0493 <
0494     // real types
0495     typename Geometry1,
0496     typename Geometry2,
0497     typename GeometryOut,
0498     overlay_type OverlayType,
0499     // orientation
0500     bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
0501     bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
0502     // tag dispatching:
0503     typename TagIn1 = tag_t<Geometry1>,
0504     typename TagIn2 = tag_t<Geometry2>,
0505     typename TagOut = typename detail::setop_insert_output_tag<GeometryOut>::type,
0506     // metafunction finetuning helpers:
0507     typename CastedTagIn1 = tag_cast_t<TagIn1, areal_tag, linear_tag, pointlike_tag>,
0508     typename CastedTagIn2 = tag_cast_t<TagIn2, areal_tag, linear_tag, pointlike_tag>,
0509     typename CastedTagOut = tag_cast_t<TagOut, areal_tag, linear_tag, pointlike_tag>
0510 >
0511 struct intersection_insert
0512 {
0513     BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0514         "Not or not yet implemented for these Geometry types or their order.",
0515         Geometry1, Geometry2, GeometryOut,
0516         std::integral_constant<overlay_type, OverlayType>);
0517 };
0518 
0519 
0520 template
0521 <
0522     typename Geometry1, typename Geometry2,
0523     typename GeometryOut,
0524     overlay_type OverlayType,
0525     bool Reverse1, bool Reverse2,
0526     typename TagIn1, typename TagIn2, typename TagOut
0527 >
0528 struct intersection_insert
0529     <
0530         Geometry1, Geometry2,
0531         GeometryOut,
0532         OverlayType,
0533         Reverse1, Reverse2,
0534         TagIn1, TagIn2, TagOut,
0535         areal_tag, areal_tag, areal_tag
0536     > : detail::overlay::overlay
0537         <
0538             Geometry1, Geometry2, Reverse1, Reverse2,
0539             detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
0540             GeometryOut, OverlayType
0541         >
0542 {};
0543 
0544 
0545 // Any areal type with box:
0546 template
0547 <
0548     typename Geometry, typename Box,
0549     typename GeometryOut,
0550     overlay_type OverlayType,
0551     bool Reverse1, bool Reverse2,
0552     typename TagIn, typename TagOut
0553 >
0554 struct intersection_insert
0555     <
0556         Geometry, Box,
0557         GeometryOut,
0558         OverlayType,
0559         Reverse1, Reverse2,
0560         TagIn, box_tag, TagOut,
0561         areal_tag, areal_tag, areal_tag
0562     > : detail::overlay::overlay
0563         <
0564             Geometry, Box, Reverse1, Reverse2,
0565             detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
0566             GeometryOut, OverlayType
0567         >
0568 {};
0569 
0570 
0571 template
0572 <
0573     typename Segment1, typename Segment2,
0574     typename GeometryOut,
0575     overlay_type OverlayType,
0576     bool Reverse1, bool Reverse2
0577 >
0578 struct intersection_insert
0579     <
0580         Segment1, Segment2,
0581         GeometryOut,
0582         OverlayType,
0583         Reverse1, Reverse2,
0584         segment_tag, segment_tag, point_tag,
0585         linear_tag, linear_tag, pointlike_tag
0586     > : detail::intersection::intersection_segment_segment_point<GeometryOut>
0587 {};
0588 
0589 
0590 template
0591 <
0592     typename Linestring1, typename Linestring2,
0593     typename GeometryOut,
0594     overlay_type OverlayType,
0595     bool Reverse1, bool Reverse2
0596 >
0597 struct intersection_insert
0598     <
0599         Linestring1, Linestring2,
0600         GeometryOut,
0601         OverlayType,
0602         Reverse1, Reverse2,
0603         linestring_tag, linestring_tag, point_tag,
0604         linear_tag, linear_tag, pointlike_tag
0605     > : detail::intersection::intersection_linestring_linestring_point<GeometryOut>
0606 {};
0607 
0608 
0609 template
0610 <
0611     typename Linestring, typename Box,
0612     typename GeometryOut,
0613     bool Reverse1, bool Reverse2
0614 >
0615 struct intersection_insert
0616     <
0617         Linestring, Box,
0618         GeometryOut,
0619         overlay_intersection,
0620         Reverse1, Reverse2,
0621         linestring_tag, box_tag, linestring_tag,
0622         linear_tag, areal_tag, linear_tag
0623     >
0624 {
0625     template <typename OutputIterator, typename Strategy>
0626     static inline OutputIterator apply(Linestring const& linestring,
0627             Box const& box,
0628             OutputIterator out, Strategy const& )
0629     {
0630         strategy::intersection::liang_barsky<Box, point_type_t<GeometryOut>> lb_strategy;
0631         return detail::intersection::clip_range_with_box
0632             <GeometryOut>(box, linestring, out, lb_strategy);
0633     }
0634 };
0635 
0636 
0637 template
0638 <
0639     typename Linestring, typename Polygon,
0640     typename GeometryOut,
0641     overlay_type OverlayType,
0642     bool ReverseLinestring, bool ReversePolygon
0643 >
0644 struct intersection_insert
0645     <
0646         Linestring, Polygon,
0647         GeometryOut,
0648         OverlayType,
0649         ReverseLinestring, ReversePolygon,
0650         linestring_tag, polygon_tag, linestring_tag,
0651         linear_tag, areal_tag, linear_tag
0652     > : detail::intersection::intersection_of_linestring_with_areal
0653             <
0654                 ReversePolygon,
0655                 GeometryOut,
0656                 OverlayType,
0657                 false
0658             >
0659 {};
0660 
0661 
0662 template
0663 <
0664     typename Linestring, typename Ring,
0665     typename GeometryOut,
0666     overlay_type OverlayType,
0667     bool ReverseLinestring, bool ReverseRing
0668 >
0669 struct intersection_insert
0670     <
0671         Linestring, Ring,
0672         GeometryOut,
0673         OverlayType,
0674         ReverseLinestring, ReverseRing,
0675         linestring_tag, ring_tag, linestring_tag,
0676         linear_tag, areal_tag, linear_tag
0677     > : detail::intersection::intersection_of_linestring_with_areal
0678             <
0679                 ReverseRing,
0680                 GeometryOut,
0681                 OverlayType,
0682                 false
0683             >
0684 {};
0685 
0686 template
0687 <
0688     typename Segment, typename Box,
0689     typename GeometryOut,
0690     overlay_type OverlayType,
0691     bool Reverse1, bool Reverse2
0692 >
0693 struct intersection_insert
0694     <
0695         Segment, Box,
0696         GeometryOut,
0697         OverlayType,
0698         Reverse1, Reverse2,
0699         segment_tag, box_tag, linestring_tag,
0700         linear_tag, areal_tag, linear_tag
0701     >
0702 {
0703     template <typename OutputIterator, typename Strategy>
0704     static inline OutputIterator apply(Segment const& segment,
0705             Box const& box,
0706             OutputIterator out, Strategy const& )
0707     {
0708         geometry::segment_view<Segment> range(segment);
0709 
0710         strategy::intersection::liang_barsky<Box, point_type_t<GeometryOut>> lb_strategy;
0711         return detail::intersection::clip_range_with_box
0712             <GeometryOut>(box, range, out, lb_strategy);
0713     }
0714 };
0715 
0716 template
0717 <
0718     typename Geometry1, typename Geometry2,
0719     typename PointOut,
0720     overlay_type OverlayType,
0721     bool Reverse1, bool Reverse2,
0722     typename Tag1, typename Tag2
0723 >
0724 struct intersection_insert
0725     <
0726         Geometry1, Geometry2,
0727         PointOut,
0728         OverlayType,
0729         Reverse1, Reverse2,
0730         Tag1, Tag2, point_tag,
0731         areal_tag, areal_tag, pointlike_tag
0732     >
0733     : public detail::intersection::intersection_areal_areal_point
0734         <
0735             PointOut
0736         >
0737 {};
0738 
0739 template
0740 <
0741     typename Geometry1, typename Geometry2,
0742     typename PointOut,
0743     overlay_type OverlayType,
0744     bool Reverse1, bool Reverse2,
0745     typename Tag1, typename Tag2
0746 >
0747 struct intersection_insert
0748     <
0749         Geometry1, Geometry2,
0750         PointOut,
0751         OverlayType,
0752         Reverse1, Reverse2,
0753         Tag1, Tag2, point_tag,
0754         linear_tag, areal_tag, pointlike_tag
0755     >
0756     : public detail::intersection::intersection_linear_areal_point
0757         <
0758             PointOut
0759         >
0760 {};
0761 
0762 template
0763 <
0764     typename Geometry1, typename Geometry2,
0765     typename PointOut,
0766     overlay_type OverlayType,
0767     bool Reverse1, bool Reverse2,
0768     typename Tag1, typename Tag2
0769 >
0770 struct intersection_insert
0771     <
0772         Geometry1, Geometry2,
0773         PointOut,
0774         OverlayType,
0775         Reverse1, Reverse2,
0776         Tag1, Tag2, point_tag,
0777         areal_tag, linear_tag, pointlike_tag
0778     >
0779     : public detail::intersection::intersection_areal_linear_point
0780         <
0781             PointOut
0782         >
0783 {};
0784 
0785 template
0786 <
0787     typename Geometry1, typename Geometry2, typename GeometryOut,
0788     overlay_type OverlayType,
0789     bool Reverse1, bool Reverse2
0790 >
0791 struct intersection_insert_reversed
0792 {
0793     template <typename OutputIterator, typename Strategy>
0794     static inline OutputIterator apply(Geometry1 const& g1,
0795                 Geometry2 const& g2,
0796                 OutputIterator out,
0797                 Strategy const& strategy)
0798     {
0799         return intersection_insert
0800             <
0801                 Geometry2, Geometry1, GeometryOut,
0802                 OverlayType,
0803                 Reverse2, Reverse1
0804             >::apply(g2, g1, out, strategy);
0805     }
0806 };
0807 
0808 
0809 // dispatch for intersection(areal, areal, linear)
0810 template
0811 <
0812     typename Geometry1, typename Geometry2,
0813     typename LinestringOut,
0814     bool Reverse1, bool Reverse2,
0815     typename Tag1, typename Tag2
0816 >
0817 struct intersection_insert
0818     <
0819         Geometry1, Geometry2,
0820         LinestringOut,
0821         overlay_intersection,
0822         Reverse1, Reverse2,
0823         Tag1, Tag2, linestring_tag,
0824         areal_tag, areal_tag, linear_tag
0825     >
0826 {
0827     template
0828     <
0829         typename OutputIterator, typename Strategy
0830     >
0831     static inline OutputIterator apply(Geometry1 const& geometry1,
0832                                        Geometry2 const& geometry2,
0833                                        OutputIterator oit,
0834                                        Strategy const& strategy)
0835     {
0836         detail::boundary_view<Geometry1 const> view1(geometry1);
0837         detail::boundary_view<Geometry2 const> view2(geometry2);
0838 
0839         return detail::overlay::linear_linear_linestring
0840             <
0841                 detail::boundary_view<Geometry1 const>,
0842                 detail::boundary_view<Geometry2 const>,
0843                 LinestringOut,
0844                 overlay_intersection
0845             >::apply(view1, view2, oit, strategy);
0846     }
0847 };
0848 
0849 // dispatch for difference/intersection of linear geometries
0850 template
0851 <
0852     typename Linear1, typename Linear2, typename LineStringOut,
0853     overlay_type OverlayType,
0854     bool Reverse1, bool Reverse2,
0855     typename TagIn1, typename TagIn2
0856 >
0857 struct intersection_insert
0858     <
0859         Linear1, Linear2, LineStringOut, OverlayType,
0860         Reverse1, Reverse2,
0861         TagIn1, TagIn2, linestring_tag,
0862         linear_tag, linear_tag, linear_tag
0863     > : detail::overlay::linear_linear_linestring
0864         <
0865             Linear1, Linear2, LineStringOut, OverlayType
0866         >
0867 {};
0868 
0869 template
0870 <
0871     typename Linear1, typename Linear2, typename TupledOut,
0872     overlay_type OverlayType,
0873     bool Reverse1, bool Reverse2,
0874     typename TagIn1, typename TagIn2
0875 >
0876 struct intersection_insert
0877     <
0878         Linear1, Linear2, TupledOut, OverlayType,
0879         Reverse1, Reverse2,
0880         TagIn1, TagIn2, detail::tupled_output_tag,
0881         linear_tag, linear_tag, detail::tupled_output_tag
0882     >
0883     : detail::expect_output
0884         <
0885             Linear1, Linear2, TupledOut,
0886             // NOTE: points can be the result only in case of intersection.
0887             std::conditional_t
0888                 <
0889                     (OverlayType == overlay_intersection),
0890                     point_tag,
0891                     void
0892                 >,
0893             linestring_tag
0894         >
0895 {
0896     // NOTE: The order of geometries in TupledOut tuple/pair must correspond to the order
0897     // iterators in OutputIterators tuple/pair.
0898     template
0899     <
0900         typename OutputIterators, typename Strategy
0901     >
0902     static inline OutputIterators apply(Linear1 const& linear1,
0903                                         Linear2 const& linear2,
0904                                         OutputIterators oit,
0905                                         Strategy const& strategy)
0906     {
0907         return detail::overlay::linear_linear_linestring
0908             <
0909                 Linear1, Linear2, TupledOut, OverlayType
0910             >::apply(linear1, linear2, oit, strategy);
0911     }
0912 };
0913 
0914 
0915 // dispatch for difference/intersection of point-like geometries
0916 
0917 template
0918 <
0919     typename Point1, typename Point2, typename PointOut,
0920     overlay_type OverlayType,
0921     bool Reverse1, bool Reverse2
0922 >
0923 struct intersection_insert
0924     <
0925         Point1, Point2, PointOut, OverlayType,
0926         Reverse1, Reverse2,
0927         point_tag, point_tag, point_tag,
0928         pointlike_tag, pointlike_tag, pointlike_tag
0929     > : detail::overlay::point_point_point
0930         <
0931             Point1, Point2, PointOut, OverlayType
0932         >
0933 {};
0934 
0935 
0936 template
0937 <
0938     typename MultiPoint, typename Point, typename PointOut,
0939     overlay_type OverlayType,
0940     bool Reverse1, bool Reverse2
0941 >
0942 struct intersection_insert
0943     <
0944         MultiPoint, Point, PointOut, OverlayType,
0945         Reverse1, Reverse2,
0946         multi_point_tag, point_tag, point_tag,
0947         pointlike_tag, pointlike_tag, pointlike_tag
0948     > : detail::overlay::multipoint_point_point
0949         <
0950             MultiPoint, Point, PointOut, OverlayType
0951         >
0952 {};
0953 
0954 
0955 template
0956 <
0957     typename Point, typename MultiPoint, typename PointOut,
0958     overlay_type OverlayType,
0959     bool Reverse1, bool Reverse2
0960 >
0961 struct intersection_insert
0962     <
0963         Point, MultiPoint, PointOut, OverlayType,
0964         Reverse1, Reverse2,
0965         point_tag, multi_point_tag, point_tag,
0966         pointlike_tag, pointlike_tag, pointlike_tag
0967     > : detail::overlay::point_multipoint_point
0968         <
0969             Point, MultiPoint, PointOut, OverlayType
0970         >
0971 {};
0972 
0973 
0974 template
0975 <
0976     typename MultiPoint1, typename MultiPoint2, typename PointOut,
0977     overlay_type OverlayType,
0978     bool Reverse1, bool Reverse2
0979 >
0980 struct intersection_insert
0981     <
0982         MultiPoint1, MultiPoint2, PointOut, OverlayType,
0983         Reverse1, Reverse2,
0984         multi_point_tag, multi_point_tag, point_tag,
0985         pointlike_tag, pointlike_tag, pointlike_tag
0986     > : detail::overlay::multipoint_multipoint_point
0987         <
0988             MultiPoint1, MultiPoint2, PointOut, OverlayType
0989         >
0990 {};
0991 
0992 
0993 template
0994 <
0995     typename PointLike1, typename PointLike2, typename TupledOut,
0996     overlay_type OverlayType,
0997     bool Reverse1, bool Reverse2,
0998     typename TagIn1, typename TagIn2
0999 >
1000 struct intersection_insert
1001     <
1002         PointLike1, PointLike2, TupledOut, OverlayType,
1003         Reverse1, Reverse2,
1004         TagIn1, TagIn2, detail::tupled_output_tag,
1005         pointlike_tag, pointlike_tag, detail::tupled_output_tag
1006     >
1007     : detail::expect_output<PointLike1, PointLike2, TupledOut, point_tag>
1008 {
1009     // NOTE: The order of geometries in TupledOut tuple/pair must correspond to the order
1010     // of iterators in OutputIterators tuple/pair.
1011     template
1012     <
1013         typename OutputIterators, typename Strategy
1014     >
1015     static inline OutputIterators apply(PointLike1 const& pointlike1,
1016                                         PointLike2 const& pointlike2,
1017                                         OutputIterators oits,
1018                                         Strategy const& strategy)
1019     {
1020         namespace bgt = boost::geometry::tuples;
1021 
1022         static const bool out_point_index = bgt::find_index_if
1023             <
1024                 TupledOut, geometry::detail::is_tag_same_as_pred<point_tag>::template pred
1025             >::value;
1026 
1027         bgt::get<out_point_index>(oits) = intersection_insert
1028             <
1029                 PointLike1, PointLike2,
1030                 typename bgt::element
1031                     <
1032                         out_point_index, TupledOut
1033                     >::type,
1034                 OverlayType
1035             >::apply(pointlike1, pointlike2,
1036                      bgt::get<out_point_index>(oits),
1037                      strategy);
1038 
1039         return oits;
1040     }
1041 };
1042 
1043 
1044 // dispatch for difference/intersection of pointlike-linear geometries
1045 template
1046 <
1047     typename Point, typename Linear, typename PointOut,
1048     overlay_type OverlayType,
1049     bool Reverse1, bool Reverse2,
1050     typename Tag
1051 >
1052 struct intersection_insert
1053     <
1054         Point, Linear, PointOut, OverlayType,
1055         Reverse1, Reverse2,
1056         point_tag, Tag, point_tag,
1057         pointlike_tag, linear_tag, pointlike_tag
1058     > : detail_dispatch::overlay::pointlike_linear_point
1059         <
1060             Point, Linear, PointOut, OverlayType,
1061             point_tag, tag_cast_t<Tag, segment_tag, linear_tag>
1062         >
1063 {};
1064 
1065 
1066 template
1067 <
1068     typename MultiPoint, typename Linear, typename PointOut,
1069     overlay_type OverlayType,
1070     bool Reverse1, bool Reverse2,
1071     typename Tag
1072 >
1073 struct intersection_insert
1074     <
1075         MultiPoint, Linear, PointOut, OverlayType,
1076         Reverse1, Reverse2,
1077         multi_point_tag, Tag, point_tag,
1078         pointlike_tag, linear_tag, pointlike_tag
1079     > : detail_dispatch::overlay::pointlike_linear_point
1080         <
1081             MultiPoint, Linear, PointOut, OverlayType,
1082             multi_point_tag,
1083             tag_cast_t<Tag, segment_tag, linear_tag>
1084         >
1085 {};
1086 
1087 
1088 // This specialization is needed because intersection() reverses the arguments
1089 // for MultiPoint/Linestring combination.
1090 template
1091 <
1092     typename Linestring, typename MultiPoint, typename PointOut,
1093     bool Reverse1, bool Reverse2
1094 >
1095 struct intersection_insert
1096     <
1097         Linestring, MultiPoint, PointOut, overlay_intersection,
1098         Reverse1, Reverse2,
1099         linestring_tag, multi_point_tag, point_tag,
1100         linear_tag, pointlike_tag, pointlike_tag
1101     >
1102 {
1103     template <typename OutputIterator, typename Strategy>
1104     static inline OutputIterator apply(Linestring const& linestring,
1105                                        MultiPoint const& multipoint,
1106                                        OutputIterator out,
1107                                        Strategy const& strategy)
1108     {
1109         return detail_dispatch::overlay::pointlike_linear_point
1110             <
1111                 MultiPoint, Linestring, PointOut, overlay_intersection,
1112                 multi_point_tag, linear_tag
1113             >::apply(multipoint, linestring, out, strategy);
1114     }
1115 };
1116 
1117 
1118 template
1119 <
1120     typename PointLike, typename Linear, typename TupledOut,
1121     overlay_type OverlayType,
1122     bool Reverse1, bool Reverse2,
1123     typename TagIn1, typename TagIn2
1124 >
1125 struct intersection_insert
1126     <
1127         PointLike, Linear, TupledOut, OverlayType,
1128         Reverse1, Reverse2,
1129         TagIn1, TagIn2, detail::tupled_output_tag,
1130         pointlike_tag, linear_tag, detail::tupled_output_tag
1131     >
1132     // Reuse the implementation for PointLike/PointLike.
1133     : intersection_insert
1134         <
1135             PointLike, Linear, TupledOut, OverlayType,
1136             Reverse1, Reverse2,
1137             TagIn1, TagIn2, detail::tupled_output_tag,
1138             pointlike_tag, pointlike_tag, detail::tupled_output_tag
1139         >
1140 {};
1141 
1142 
1143 // This specialization is needed because intersection() reverses the arguments
1144 // for MultiPoint/Linestring combination.
1145 template
1146 <
1147     typename Linestring, typename MultiPoint, typename TupledOut,
1148     bool Reverse1, bool Reverse2
1149 >
1150 struct intersection_insert
1151     <
1152         Linestring, MultiPoint, TupledOut, overlay_intersection,
1153         Reverse1, Reverse2,
1154         linestring_tag, multi_point_tag, detail::tupled_output_tag,
1155         linear_tag, pointlike_tag, detail::tupled_output_tag
1156     >
1157 {
1158     template <typename OutputIterators, typename Strategy>
1159     static inline OutputIterators apply(Linestring const& linestring,
1160                                         MultiPoint const& multipoint,
1161                                         OutputIterators out,
1162                                         Strategy const& strategy)
1163     {
1164         return intersection_insert
1165             <
1166                 MultiPoint, Linestring, TupledOut, overlay_intersection
1167             >::apply(multipoint, linestring, out, strategy);
1168     }
1169 };
1170 
1171 
1172 // dispatch for difference/intersection of pointlike-areal geometries
1173 template
1174 <
1175     typename Point, typename Areal, typename PointOut,
1176     overlay_type OverlayType,
1177     bool Reverse1, bool Reverse2,
1178     typename ArealTag
1179 >
1180 struct intersection_insert
1181     <
1182         Point, Areal, PointOut, OverlayType,
1183         Reverse1, Reverse2,
1184         point_tag, ArealTag, point_tag,
1185         pointlike_tag, areal_tag, pointlike_tag
1186     > : detail_dispatch::overlay::pointlike_areal_point
1187         <
1188             Point, Areal, PointOut, OverlayType,
1189             point_tag, ArealTag
1190         >
1191 {};
1192 
1193 template
1194 <
1195     typename MultiPoint, typename Areal, typename PointOut,
1196     overlay_type OverlayType,
1197     bool Reverse1, bool Reverse2,
1198     typename ArealTag
1199 >
1200 struct intersection_insert
1201     <
1202         MultiPoint, Areal, PointOut, OverlayType,
1203         Reverse1, Reverse2,
1204         multi_point_tag, ArealTag, point_tag,
1205         pointlike_tag, areal_tag, pointlike_tag
1206     > : detail_dispatch::overlay::pointlike_areal_point
1207         <
1208             MultiPoint, Areal, PointOut, OverlayType,
1209             multi_point_tag, ArealTag
1210         >
1211 {};
1212 
1213 // This specialization is needed because intersection() reverses the arguments
1214 // for MultiPoint/Ring and MultiPoint/Polygon combinations.
1215 template
1216 <
1217     typename Areal, typename MultiPoint, typename PointOut,
1218     bool Reverse1, bool Reverse2,
1219     typename ArealTag
1220 >
1221 struct intersection_insert
1222     <
1223         Areal, MultiPoint, PointOut, overlay_intersection,
1224         Reverse1, Reverse2,
1225         ArealTag, multi_point_tag, point_tag,
1226         areal_tag, pointlike_tag, pointlike_tag
1227     >
1228 {
1229     template <typename OutputIterator, typename Strategy>
1230     static inline OutputIterator apply(Areal const& areal,
1231                                        MultiPoint const& multipoint,
1232                                        OutputIterator out,
1233                                        Strategy const& strategy)
1234     {
1235         return detail_dispatch::overlay::pointlike_areal_point
1236             <
1237                 MultiPoint, Areal, PointOut, overlay_intersection,
1238                 multi_point_tag, ArealTag
1239             >::apply(multipoint, areal, out, strategy);
1240     }
1241 };
1242 
1243 
1244 template
1245 <
1246     typename PointLike, typename Areal, typename TupledOut,
1247     overlay_type OverlayType,
1248     bool Reverse1, bool Reverse2,
1249     typename TagIn1, typename TagIn2
1250 >
1251 struct intersection_insert
1252     <
1253         PointLike, Areal, TupledOut, OverlayType,
1254         Reverse1, Reverse2,
1255         TagIn1, TagIn2, detail::tupled_output_tag,
1256         pointlike_tag, areal_tag, detail::tupled_output_tag
1257     >
1258     // Reuse the implementation for PointLike/PointLike.
1259     : intersection_insert
1260         <
1261             PointLike, Areal, TupledOut, OverlayType,
1262             Reverse1, Reverse2,
1263             TagIn1, TagIn2, detail::tupled_output_tag,
1264             pointlike_tag, pointlike_tag, detail::tupled_output_tag
1265         >
1266 {};
1267 
1268 
1269 // This specialization is needed because intersection() reverses the arguments
1270 // for MultiPoint/Ring and MultiPoint/Polygon combinations.
1271 template
1272 <
1273     typename Areal, typename MultiPoint, typename TupledOut,
1274     bool Reverse1, bool Reverse2,
1275     typename TagIn1
1276 >
1277 struct intersection_insert
1278     <
1279         Areal, MultiPoint, TupledOut, overlay_intersection,
1280         Reverse1, Reverse2,
1281         TagIn1, multi_point_tag, detail::tupled_output_tag,
1282         areal_tag, pointlike_tag, detail::tupled_output_tag
1283     >
1284 {
1285     template <typename OutputIterators, typename Strategy>
1286     static inline OutputIterators apply(Areal const& areal,
1287                                         MultiPoint const& multipoint,
1288                                         OutputIterators out,
1289                                         Strategy const& strategy)
1290     {
1291         return intersection_insert
1292             <
1293                 MultiPoint, Areal, TupledOut, overlay_intersection
1294             >::apply(multipoint, areal, out, strategy);
1295     }
1296 };
1297 
1298 
1299 template
1300 <
1301     typename Linestring, typename Polygon,
1302     typename TupledOut,
1303     overlay_type OverlayType,
1304     bool ReverseLinestring, bool ReversePolygon
1305 >
1306 struct intersection_insert
1307     <
1308         Linestring, Polygon,
1309         TupledOut,
1310         OverlayType,
1311         ReverseLinestring, ReversePolygon,
1312         linestring_tag, polygon_tag, detail::tupled_output_tag,
1313         linear_tag, areal_tag, detail::tupled_output_tag
1314     > : detail::intersection::intersection_of_linestring_with_areal
1315             <
1316                 ReversePolygon,
1317                 TupledOut,
1318                 OverlayType,
1319                 true
1320             >
1321 {};
1322 
1323 template
1324 <
1325     typename Linestring, typename Ring,
1326     typename TupledOut,
1327     overlay_type OverlayType,
1328     bool ReverseLinestring, bool ReverseRing
1329 >
1330 struct intersection_insert
1331     <
1332         Linestring, Ring,
1333         TupledOut,
1334         OverlayType,
1335         ReverseLinestring, ReverseRing,
1336         linestring_tag, ring_tag, detail::tupled_output_tag,
1337         linear_tag, areal_tag, detail::tupled_output_tag
1338     > : detail::intersection::intersection_of_linestring_with_areal
1339             <
1340                 ReverseRing,
1341                 TupledOut,
1342                 OverlayType,
1343                 true
1344             >
1345 {};
1346 
1347 
1348 } // namespace dispatch
1349 #endif // DOXYGEN_NO_DISPATCH
1350 
1351 
1352 #ifndef DOXYGEN_NO_DETAIL
1353 namespace detail { namespace intersection
1354 {
1355 
1356 
1357 template
1358 <
1359     typename GeometryOut,
1360     bool ReverseSecond,
1361     overlay_type OverlayType,
1362     typename Geometry1, typename Geometry2,
1363     typename OutputIterator,
1364     typename Strategy
1365 >
1366 inline OutputIterator insert(Geometry1 const& geometry1,
1367             Geometry2 const& geometry2,
1368             OutputIterator out,
1369             Strategy const& strategy)
1370 {
1371     return std::conditional_t
1372         <
1373             geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
1374             geometry::dispatch::intersection_insert_reversed
1375             <
1376                 Geometry1, Geometry2,
1377                 GeometryOut,
1378                 OverlayType,
1379                 overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
1380                 overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value
1381             >,
1382             geometry::dispatch::intersection_insert
1383             <
1384                 Geometry1, Geometry2,
1385                 GeometryOut,
1386                 OverlayType,
1387                 geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
1388                 geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value
1389             >
1390         >::apply(geometry1, geometry2, out, strategy);
1391 }
1392 
1393 
1394 /*!
1395 \brief \brief_calc2{intersection} \brief_strategy
1396 \ingroup intersection
1397 \details \details_calc2{intersection_insert, spatial set theoretic intersection}
1398     \brief_strategy. \details_insert{intersection}
1399 \tparam GeometryOut \tparam_geometry{\p_l_or_c}
1400 \tparam Geometry1 \tparam_geometry
1401 \tparam Geometry2 \tparam_geometry
1402 \tparam OutputIterator \tparam_out{\p_l_or_c}
1403 \tparam Strategy \tparam_strategy_overlay
1404 \param geometry1 \param_geometry
1405 \param geometry2 \param_geometry
1406 \param out \param_out{intersection}
1407 \param strategy \param_strategy{intersection}
1408 \return \return_out
1409 
1410 \qbk{distinguish,with strategy}
1411 \qbk{[include reference/algorithms/intersection.qbk]}
1412 */
1413 template
1414 <
1415     typename GeometryOut,
1416     typename Geometry1,
1417     typename Geometry2,
1418     typename OutputIterator,
1419     typename Strategy
1420 >
1421 inline OutputIterator intersection_insert(Geometry1 const& geometry1,
1422             Geometry2 const& geometry2,
1423             OutputIterator out,
1424             Strategy const& strategy)
1425 {
1426     concepts::check<Geometry1 const>();
1427     concepts::check<Geometry2 const>();
1428 
1429     return detail::intersection::insert
1430         <
1431             GeometryOut, false, overlay_intersection
1432         >(geometry1, geometry2, out, strategy);
1433 }
1434 
1435 
1436 /*!
1437 \brief \brief_calc2{intersection}
1438 \ingroup intersection
1439 \details \details_calc2{intersection_insert, spatial set theoretic intersection}.
1440     \details_insert{intersection}
1441 \tparam GeometryOut \tparam_geometry{\p_l_or_c}
1442 \tparam Geometry1 \tparam_geometry
1443 \tparam Geometry2 \tparam_geometry
1444 \tparam OutputIterator \tparam_out{\p_l_or_c}
1445 \param geometry1 \param_geometry
1446 \param geometry2 \param_geometry
1447 \param out \param_out{intersection}
1448 \return \return_out
1449 
1450 \qbk{[include reference/algorithms/intersection.qbk]}
1451 */
1452 template
1453 <
1454     typename GeometryOut,
1455     typename Geometry1,
1456     typename Geometry2,
1457     typename OutputIterator
1458 >
1459 inline OutputIterator intersection_insert(Geometry1 const& geometry1,
1460             Geometry2 const& geometry2,
1461             OutputIterator out)
1462 {
1463     concepts::check<Geometry1 const>();
1464     concepts::check<Geometry2 const>();
1465 
1466     using strategy_type = typename strategies::relate::services::default_strategy
1467         <
1468             Geometry1, Geometry2
1469         >::type;
1470 
1471     return intersection_insert<GeometryOut>(geometry1, geometry2, out,
1472                                             strategy_type());
1473 }
1474 
1475 }} // namespace detail::intersection
1476 #endif // DOXYGEN_NO_DETAIL
1477 
1478 
1479 
1480 }} // namespace boost::geometry
1481 
1482 
1483 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP