]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/geometry/algorithms/detail/overlay/follow.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / overlay / follow.hpp
index ac9978b494ba9a32d77901ceaff646c5d497a3cc..303e1cd02b32064ef8d652582411ef680c22123b 100644 (file)
@@ -3,8 +3,8 @@
 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
 // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
 
-// This file was modified by Oracle on 2014, 2017, 2018, 2019.
-// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014, 2017, 2018, 2019, 2020.
+// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
 
@@ -28,7 +28,7 @@
 #include <boost/geometry/algorithms/covered_by.hpp>
 #include <boost/geometry/algorithms/clear.hpp>
 #include <boost/geometry/algorithms/detail/relate/turns.hpp>
-
+#include <boost/geometry/algorithms/detail/tupled_output.hpp>
 
 namespace boost { namespace geometry
 {
@@ -42,7 +42,7 @@ namespace following
 {
 
 template <typename Turn, typename Operation>
-static inline bool is_entering(Turn const& /* TODO remove this parameter */, Operation const& op)
+inline bool is_entering(Turn const& /* TODO remove this parameter */, Operation const& op)
 {
     // (Blocked means: blocked for polygon/polygon intersection, because
     // they are reversed. But for polygon/line it is similar to continue)
@@ -60,7 +60,7 @@ template
     typename Polygon,
     typename PtInPolyStrategy
 >
-static inline bool last_covered_by(Turn const& /*turn*/, Operation const& op,
+inline bool last_covered_by(Turn const& /*turn*/, Operation const& op,
                 LineString const& linestring, Polygon const& polygon,
                 PtInPolyStrategy const& strategy)
 {
@@ -76,7 +76,7 @@ template
     typename Polygon,
     typename PtInPolyStrategy
 >
-static inline bool is_leaving(Turn const& turn, Operation const& op,
+inline bool is_leaving(Turn const& turn, Operation const& op,
                 bool entered, bool first,
                 LineString const& linestring, Polygon const& polygon,
                 PtInPolyStrategy const& strategy)
@@ -85,7 +85,9 @@ static inline bool is_leaving(Turn const& turn, Operation const& op,
     {
         return entered
             || turn.method == method_crosses
-            || (first && last_covered_by(turn, op, linestring, polygon, strategy))
+            || (first
+                && op.position != position_front
+                && last_covered_by(turn, op, linestring, polygon, strategy))
             ;
     }
     return false;
@@ -100,7 +102,7 @@ template
     typename Polygon,
     typename PtInPolyStrategy
 >
-static inline bool is_staying_inside(Turn const& turn, Operation const& op,
+inline bool is_staying_inside(Turn const& turn, Operation const& op,
                 bool entered, bool first,
                 LineString const& linestring, Polygon const& polygon,
                 PtInPolyStrategy const& strategy)
@@ -128,7 +130,7 @@ template
     typename Polygon,
     typename PtInPolyStrategy
 >
-static inline bool was_entered(Turn const& turn, Operation const& op, bool first,
+inline bool was_entered(Turn const& turn, Operation const& op, bool first,
                 Linestring const& linestring, Polygon const& polygon,
                 PtInPolyStrategy const& strategy)
 {
@@ -139,6 +141,60 @@ static inline bool was_entered(Turn const& turn, Operation const& op, bool first
     return false;
 }
 
+template
+<
+    typename Turn,
+    typename Operation
+>
+inline bool is_touching(Turn const& turn, Operation const& op,
+                        bool entered)
+{
+    return (op.operation == operation_union || op.operation == operation_blocked)
+        && (turn.method == method_touch || turn.method == method_touch_interior)
+        && !entered
+        && !op.is_collinear;
+}
+
+
+template
+<
+    typename GeometryOut,
+    typename Tag = typename geometry::tag<GeometryOut>::type
+>
+struct add_isolated_point
+{};
+
+template <typename LineStringOut>
+struct add_isolated_point<LineStringOut, linestring_tag>
+{
+    template <typename Point, typename OutputIterator>
+    static inline void apply(Point const& point, OutputIterator& out)
+    {
+        LineStringOut isolated_point_ls;
+        geometry::append(isolated_point_ls, point);
+
+#ifndef BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS
+        geometry::append(isolated_point_ls, point);
+#endif // BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS
+
+        *out++ = isolated_point_ls;
+    }
+};
+
+template <typename PointOut>
+struct add_isolated_point<PointOut, point_tag>
+{
+    template <typename Point, typename OutputIterator>
+    static inline void apply(Point const& point, OutputIterator& out)
+    {
+        PointOut isolated_point;
+
+        geometry::detail::conversion::convert_point_to_point(point, isolated_point);
+
+        *out++ = isolated_point;
+    }
+};
+
 
 // Template specialization structure to call the right actions for the right type
 template <overlay_type OverlayType, bool RemoveSpikes = true>
@@ -213,26 +269,14 @@ struct action_selector<overlay_intersection, RemoveSpikes>
 
     template
     <
-        typename OutputIterator,
-        typename LineStringOut,
-        typename LineString,
+        typename LineStringOrPointOut,
         typename Point,
-        typename Operation
+        typename OutputIterator
     >
-    static inline void isolated_point(LineStringOut&,
-                LineString const&,
-                segment_identifier&,
-                signed_size_type, Point const& point,
-                Operation const& , OutputIterator& out)
+    static inline void isolated_point(Point const& point,
+                                      OutputIterator& out)
     {
-        LineStringOut isolated_point_ls;
-        geometry::append(isolated_point_ls, point);
-
-#ifndef BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS
-        geometry::append(isolated_point_ls, point);
-#endif // BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS
-
-        *out++ = isolated_point_ls;
+        add_isolated_point<LineStringOrPointOut>::apply(point, out);
     }
 
     static inline bool is_entered(bool entered)
@@ -301,17 +345,12 @@ struct action_selector<overlay_difference, RemoveSpikes>
 
     template
     <
-        typename OutputIterator,
-        typename LineStringOut,
-        typename LineString,
+        typename LineStringOrPointOut,
         typename Point,
-        typename Operation
+        typename OutputIterator
     >
-    static inline void isolated_point(LineStringOut&,
-                LineString const&,
-                segment_identifier&,
-                signed_size_type, Point const&,
-                Operation const&, OutputIterator&)
+    static inline void isolated_point(Point const&,
+                                      OutputIterator const&)
     {
     }
 
@@ -327,7 +366,7 @@ struct action_selector<overlay_difference, RemoveSpikes>
 
 };
 
-}
+} // namespace following
 
 /*!
 \brief Follows a linestring from intersection point to intersection point, outputting which
@@ -336,64 +375,23 @@ struct action_selector<overlay_difference, RemoveSpikes>
  */
 template
 <
-    typename LineStringOut,
+    typename GeometryOut,
     typename LineString,
     typename Polygon,
     overlay_type OverlayType,
-    bool RemoveSpikes = true
+    bool RemoveSpikes,
+    bool FollowIsolatedPoints
 >
 class follow
 {
-
-#ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
-    template <typename Turn>
-    struct sort_on_segment
-    {
-        // In case of turn point at the same location, we want to have continue/blocked LAST
-        // because that should be followed (intersection) or skipped (difference).
-        inline int operation_order(Turn const& turn) const
-        {
-            operation_type const& operation = turn.operations[0].operation;
-            switch(operation)
-            {
-                case operation_opposite : return 0;
-                case operation_none : return 0;
-                case operation_union : return 1;
-                case operation_intersection : return 2;
-                case operation_blocked : return 3;
-                case operation_continue : return 4;
-            }
-            return -1;
-        };
-
-        inline bool use_operation(Turn const& left, Turn const& right) const
-        {
-            // If they are the same, OK.
-            return operation_order(left) < operation_order(right);
-        }
-
-        inline bool use_distance(Turn const& left, Turn const& right) const
-        {
-            return left.operations[0].fraction == right.operations[0].fraction
-                ? use_operation(left, right)
-                : left.operations[0].fraction < right.operations[0].fraction
-                ;
-        }
-
-        inline bool operator()(Turn const& left, Turn const& right) const
-        {
-            segment_identifier const& sl = left.operations[0].seg_id;
-            segment_identifier const& sr = right.operations[0].seg_id;
-
-            return sl == sr
-                ? use_distance(left, right)
-                : sl < sr
-                ;
-
-        }
-    };
-#endif // BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
-
+    typedef geometry::detail::output_geometry_access
+        <
+            GeometryOut, linestring_tag, linestring_tag
+        > linear;
+    typedef geometry::detail::output_geometry_access
+        <
+            GeometryOut, point_tag, linestring_tag
+        > pointlike;
 
 public :
 
@@ -441,17 +439,13 @@ public :
         // sort turns by Linear seg_id, then by fraction, then
         // for same ring id: x, u, i, c
         // for different ring id: c, i, u, x
-#ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR
-        std::sort(boost::begin(turns), boost::end(turns), sort_on_segment<turn_type>());
-#else
         typedef relate::turns::less
             <
                 0, relate::turns::less_op_linear_areal_single<0>, cs_tag
             > turn_less;
         std::sort(boost::begin(turns), boost::end(turns), turn_less());
-#endif
 
-        LineStringOut current_piece;
+        typename linear::type current_piece;
         geometry::segment_identifier current_segment_id(0, -1, -1, -1);
 
         // Iterate through all intersection points (they are ordered along the line)
@@ -481,7 +475,7 @@ public :
                 action::enter(current_piece, linestring, current_segment_id,
                     iit->seg_id.segment_index, it->point, *iit,
                     strategy, robust_policy,
-                    out);
+                    linear::get(out));
             }
             else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, pt_in_poly_strategy))
             {
@@ -491,8 +485,19 @@ public :
                 action::leave(current_piece, linestring, current_segment_id,
                     iit->seg_id.segment_index, it->point, *iit,
                     strategy, robust_policy,
-                    out);
+                    linear::get(out));
+            }
+            else if (FollowIsolatedPoints
+                  && following::is_touching(*it, *iit, entered))
+            {
+                debug_traverse(*it, *iit, "-> Isolated point");
+
+                action::template isolated_point
+                    <
+                        typename pointlike::type
+                    >(it->point, pointlike::get(out));
             }
+
             first = false;
         }
 
@@ -509,10 +514,20 @@ public :
         }
 
         // Output the last one, if applicable
-        if (::boost::size(current_piece) > 1)
+        std::size_t current_piece_size = ::boost::size(current_piece);
+        if (current_piece_size > 1)
         {
-            *out++ = current_piece;
+            *linear::get(out)++ = current_piece;
         }
+        else if (FollowIsolatedPoints
+              && current_piece_size == 1)
+        {
+            action::template isolated_point
+                <
+                    typename pointlike::type
+                >(range::front(current_piece), pointlike::get(out));
+        }
+
         return out;
     }