]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / disjoint / segment_box.hpp
index fe849e10918a759d0ee156b4adc365f05f967a77..ea51f6be7a5c230aa77635a2778d40c0d40732e0 100644 (file)
@@ -5,8 +5,8 @@
 // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
 // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
 
-// This file was modified by Oracle on 2013-2017.
-// Modifications copyright (c) 2013-2017, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2019.
+// Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
 
 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
 #include <boost/geometry/algorithms/detail/envelope/segment.hpp>
 #include <boost/geometry/algorithms/detail/normalize.hpp>
 #include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
 
 #include <boost/geometry/formulas/vertex_longitude.hpp>
 
 #include <boost/geometry/geometries/box.hpp>
 
+// Temporary, for envelope_segment_impl
+#include <boost/geometry/strategies/spherical/envelope_segment.hpp>
+
 namespace boost { namespace geometry
 {
 
@@ -49,51 +53,92 @@ namespace detail { namespace disjoint
 template <typename CS_Tag>
 struct disjoint_segment_box_sphere_or_spheroid
 {
-private:
-
-    template <typename CT>
-    static inline void swap(CT& lon1,
-                            CT& lat1,
-                            CT& lon2,
-                            CT& lat2)
+    struct disjoint_info
     {
-        std::swap(lon1, lon2);
-        std::swap(lat1, lat2);
-    }
-
-
-public:
-
-    template <typename Segment, typename Box, typename Strategy>
+        enum type
+        {
+            intersect,
+            disjoint_no_vertex,
+            disjoint_vertex
+        };
+        disjoint_info(type t) : m_(t){}
+        operator type () const {return m_;}
+        type m_;
+    private :
+        //prevent automatic conversion for any other built-in types
+        template <typename T>
+        operator T () const;
+    };
+
+    template
+    <
+        typename Segment, typename Box,
+        typename AzimuthStrategy,
+        typename NormalizeStrategy,
+        typename DisjointPointBoxStrategy,
+        typename DisjointBoxBoxStrategy
+    >
     static inline bool apply(Segment const& segment,
                              Box const& box,
-                             Strategy const& azimuth_strategy)
+                             AzimuthStrategy const& azimuth_strategy,
+                             NormalizeStrategy const& normalize_strategy,
+                             DisjointPointBoxStrategy const& disjoint_point_box_strategy,
+                             DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
+    {
+        typedef typename point_type<Segment>::type segment_point;
+        segment_point vertex;
+        return apply(segment, box, vertex,
+                     azimuth_strategy,
+                     normalize_strategy,
+                     disjoint_point_box_strategy,
+                     disjoint_box_box_strategy) != disjoint_info::intersect;
+    }
+
+    template
+    <
+        typename Segment, typename Box,
+        typename P,
+        typename AzimuthStrategy,
+        typename NormalizeStrategy,
+        typename DisjointPointBoxStrategy,
+        typename DisjointBoxBoxStrategy
+    >
+    static inline disjoint_info apply(Segment const& segment,
+                                      Box const& box,
+                                      P& vertex,
+                                      AzimuthStrategy const& azimuth_strategy,
+                                      NormalizeStrategy const& ,
+                                      DisjointPointBoxStrategy const& disjoint_point_box_strategy,
+                                      DisjointBoxBoxStrategy const& disjoint_box_box_strategy)
     {
         assert_dimension_equal<Segment, Box>();
 
         typedef typename point_type<Segment>::type segment_point_type;
-        typedef typename cs_tag<Segment>::type segment_cs_type;
 
         segment_point_type p0, p1;
         geometry::detail::assign_point_from_index<0>(segment, p0);
         geometry::detail::assign_point_from_index<1>(segment, p1);
 
+        //vertex not computed here
+        disjoint_info disjoint_return_value = disjoint_info::disjoint_no_vertex;
+
         // Simplest cases first
 
         // Case 1: if box contains one of segment's endpoints then they are not disjoint
-        if (! disjoint_point_box(p0, box) || ! disjoint_point_box(p1, box))
+        if ( ! disjoint_point_box(p0, box, disjoint_point_box_strategy)
+          || ! disjoint_point_box(p1, box, disjoint_point_box_strategy) )
         {
-            return false;
+            return disjoint_info::intersect;
         }
 
         // Case 2: disjoint if bounding boxes are disjoint
 
         typedef typename coordinate_type<segment_point_type>::type CT;
 
-        segment_point_type p0_normalized =
-                geometry::detail::return_normalized<segment_point_type>(p0);
-        segment_point_type p1_normalized =
-                geometry::detail::return_normalized<segment_point_type>(p1);
+        segment_point_type p0_normalized;
+        NormalizeStrategy::apply(p0, p0_normalized);
+        segment_point_type p1_normalized;
+        NormalizeStrategy::apply(p1, p1_normalized);
 
         CT lon1 = geometry::get_as_radian<0>(p0_normalized);
         CT lat1 = geometry::get_as_radian<1>(p0_normalized);
@@ -102,52 +147,48 @@ public:
 
         if (lon1 > lon2)
         {
-            swap(lon1, lat1, lon2, lat2);
+            std::swap(lon1, lon2);
+            std::swap(lat1, lat2);
         }
 
-        //Compute alp1 outside envelope and pass it to envelope_segment_impl
-        //in order for it to be used later in the algorithm
-        CT alp1;
-
-        azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1);
-
         geometry::model::box<segment_point_type> box_seg;
 
-        geometry::detail::envelope::envelope_segment_impl<segment_cs_type>
-                ::template apply<geometry::radian>(lon1, lat1,
-                                                   lon2, lat2,
-                                                   box_seg,
-                                                   azimuth_strategy,
-                                                   alp1);
-        if (disjoint_box_box(box, box_seg))
+        strategy::envelope::detail::envelope_segment_impl
+            <
+                CS_Tag
+            >::template apply<geometry::radian>(lon1, lat1,
+                                                lon2, lat2,
+                                                box_seg,
+                                                azimuth_strategy);
+
+        if (disjoint_box_box(box, box_seg, disjoint_box_box_strategy))
         {
-            return true;
+            return disjoint_return_value;
         }
 
         // Case 3: test intersection by comparing angles
 
-        CT a_b0, a_b1, a_b2, a_b3;
+        CT alp1, a_b0, a_b1, a_b2, a_b3;
 
         CT b_lon_min = geometry::get_as_radian<geometry::min_corner, 0>(box);
         CT b_lat_min = geometry::get_as_radian<geometry::min_corner, 1>(box);
         CT b_lon_max = geometry::get_as_radian<geometry::max_corner, 0>(box);
         CT b_lat_max = geometry::get_as_radian<geometry::max_corner, 1>(box);
 
+        azimuth_strategy.apply(lon1, lat1, lon2, lat2, alp1);
         azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_min, a_b0);
         azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_min, a_b1);
         azimuth_strategy.apply(lon1, lat1, b_lon_min, b_lat_max, a_b2);
         azimuth_strategy.apply(lon1, lat1, b_lon_max, b_lat_max, a_b3);
 
-        bool b0 = alp1 > a_b0;
-        bool b1 = alp1 > a_b1;
-        bool b2 = alp1 > a_b2;
-        bool b3 = alp1 > a_b3;
+        bool b0 = formula::azimuth_side_value(alp1, a_b0) > 0;
+        bool b1 = formula::azimuth_side_value(alp1, a_b1) > 0;
+        bool b2 = formula::azimuth_side_value(alp1, a_b2) > 0;
+        bool b3 = formula::azimuth_side_value(alp1, a_b3) > 0;
 
-        // if not all box points on the same side of the segment then
-        // there is an intersection
         if (!(b0 && b1 && b2 && b3) && (b0 || b1 || b2 || b3))
         {
-            return false;
+            return disjoint_info::intersect;
         }
 
         // Case 4: The only intersection case not covered above is when all four
@@ -157,8 +198,8 @@ public:
         CT vertex_lat;
         CT lat_sum = lat1 + lat2;
 
-        if ((b0 && b1 && b2 && b3 && lat_sum > CT(0))
-                || (!(b0 && b1 && b2 && b3) && lat_sum < CT(0)))
+        if ((lat1 < b_lat_min && lat_sum > CT(0))
+                || (lat1 > b_lat_max && lat_sum < CT(0)))
         {
             CT b_lat_below; //latitude of box closest to equator
 
@@ -180,6 +221,10 @@ public:
                                             alp1,
                                             azimuth_strategy);
 
+            geometry::set_from_radian<0>(vertex, vertex_lon);
+            geometry::set_from_radian<1>(vertex, vertex_lat);
+            disjoint_return_value = disjoint_info::disjoint_vertex; //vertex_computed
+
             // Check if the vertex point is within the band defined by the
             // minimum and maximum longitude of the box; if yes, then return
             // false if the point is above the min latitude of the box; return
@@ -187,11 +232,11 @@ public:
             if (vertex_lon >= b_lon_min && vertex_lon <= b_lon_max
                     && std::abs(vertex_lat) > std::abs(b_lat_below))
             {
-                return false;
+                return disjoint_info::intersect;
             }
         }
 
-        return true;
+        return disjoint_return_value;
     }
 };