1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 
5 // This file was modified by Oracle on 2013, 2014, 2015, 2017.
6 // Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
7 
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9 
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13 
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP
16 
17 #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
18 //#include <boost/geometry/algorithms/within.hpp>
19 //#include <boost/geometry/algorithms/covered_by.hpp>
20 
21 #include <boost/geometry/algorithms/detail/relate/result.hpp>
22 #include <boost/geometry/algorithms/detail/relate/topology_check.hpp>
23 
24 #include <boost/geometry/util/condition.hpp>
25 
26 namespace boost { namespace geometry
27 {
28 
29 #ifndef DOXYGEN_NO_DETAIL
30 namespace detail { namespace relate {
31 
32 // non-point geometry
33 template <typename Point, typename Geometry, bool Transpose = false>
34 struct point_geometry
35 {
36     // TODO: interrupt only if the topology check is complex
37 
38     static const bool interruption_enabled = true;
39 
40     template <typename Result, typename Strategy>
applyboost::geometry::detail::relate::point_geometry41     static inline void apply(Point const& point, Geometry const& geometry, Result & result, Strategy const& strategy)
42     {
43         int pig = detail::within::point_in_geometry(point, geometry, strategy);
44 
45         if ( pig > 0 ) // within
46         {
47             relate::set<interior, interior, '0', Transpose>(result);
48         }
49         else if ( pig == 0 )
50         {
51             relate::set<interior, boundary, '0', Transpose>(result);
52         }
53         else // pig < 0 - not within
54         {
55             relate::set<interior, exterior, '0', Transpose>(result);
56         }
57 
58         relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
59 
60         if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
61             return;
62 
63         typedef detail::relate::topology_check<Geometry> tc_t;
64         if ( relate::may_update<exterior, interior, tc_t::interior, Transpose>(result)
65           || relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result) )
66         {
67             // the point is on the boundary
68             if ( pig == 0 )
69             {
70                 // NOTE: even for MLs, if there is at least one boundary point,
71                 // somewhere there must be another one
72                 relate::set<exterior, interior, tc_t::interior, Transpose>(result);
73                 relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
74             }
75             else
76             {
77                 // check if there is a boundary in Geometry
78                 tc_t tc(geometry);
79                 if ( tc.has_interior() )
80                     relate::set<exterior, interior, tc_t::interior, Transpose>(result);
81                 if ( tc.has_boundary() )
82                     relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
83             }
84         }
85     }
86 };
87 
88 // transposed result of point_geometry
89 template <typename Geometry, typename Point>
90 struct geometry_point
91 {
92     // TODO: interrupt only if the topology check is complex
93 
94     static const bool interruption_enabled = true;
95 
96     template <typename Result, typename Strategy>
applyboost::geometry::detail::relate::geometry_point97     static inline void apply(Geometry const& geometry, Point const& point, Result & result, Strategy const& strategy)
98     {
99         point_geometry<Point, Geometry, true>::apply(point, geometry, result, strategy);
100     }
101 };
102 
103 // TODO: rewrite the folowing:
104 
105 //// NOTE: Those tests should be consistent with within(Point, Box) and covered_by(Point, Box)
106 //// There is no EPS used in those functions, values are compared using < or <=
107 //// so comparing MIN and MAX in the same way should be fine
108 //
109 //template <typename Box, std::size_t I = 0, std::size_t D = geometry::dimension<Box>::value>
110 //struct box_has_interior
111 //{
112 //    static inline bool apply(Box const& box)
113 //    {
114 //        return geometry::get<min_corner, I>(box) < geometry::get<max_corner, I>(box)
115 //            && box_has_interior<Box, I + 1, D>::apply(box);
116 //    }
117 //};
118 //
119 //template <typename Box, std::size_t D>
120 //struct box_has_interior<Box, D, D>
121 //{
122 //    static inline bool apply(Box const&) { return true; }
123 //};
124 //
125 //// NOTE: especially important here (see the NOTE above).
126 //
127 //template <typename Box, std::size_t I = 0, std::size_t D = geometry::dimension<Box>::value>
128 //struct box_has_equal_min_max
129 //{
130 //    static inline bool apply(Box const& box)
131 //    {
132 //        return geometry::get<min_corner, I>(box) == geometry::get<max_corner, I>(box)
133 //            && box_has_equal_min_max<Box, I + 1, D>::apply(box);
134 //    }
135 //};
136 //
137 //template <typename Box, std::size_t D>
138 //struct box_has_equal_min_max<Box, D, D>
139 //{
140 //    static inline bool apply(Box const&) { return true; }
141 //};
142 //
143 //template <typename Point, typename Box>
144 //struct point_box
145 //{
146 //    static inline result apply(Point const& point, Box const& box)
147 //    {
148 //        result res;
149 //
150 //        if ( geometry::within(point, box) ) // this also means that the box has interior
151 //        {
152 //            return result("0FFFFFTTT");
153 //        }
154 //        else if ( geometry::covered_by(point, box) ) // point is on the boundary
155 //        {
156 //            //if ( box_has_interior<Box>::apply(box) )
157 //            //{
158 //            //    return result("F0FFFFTTT");
159 //            //}
160 //            //else if ( box_has_equal_min_max<Box>::apply(box) ) // no boundary outside point
161 //            //{
162 //            //    return result("F0FFFFFFT");
163 //            //}
164 //            //else // no interior outside point
165 //            //{
166 //            //    return result("F0FFFFFTT");
167 //            //}
168 //            return result("F0FFFF**T");
169 //        }
170 //        else
171 //        {
172 //            /*if ( box_has_interior<Box>::apply(box) )
173 //            {
174 //                return result("FF0FFFTTT");
175 //            }
176 //            else
177 //            {
178 //                return result("FF0FFFFTT");
179 //            }*/
180 //            return result("FF0FFF*TT");
181 //        }
182 //
183 //        return res;
184 //    }
185 //};
186 //
187 //template <typename Box, typename Point>
188 //struct box_point
189 //{
190 //    static inline result apply(Box const& box, Point const& point)
191 //    {
192 //        if ( geometry::within(point, box) )
193 //            return result("0FTFFTFFT");
194 //        else if ( geometry::covered_by(point, box) )
195 //            return result("FF*0F*FFT");
196 //        else
197 //            return result("FF*FFT0FT");
198 //    }
199 //};
200 
201 }} // namespace detail::relate
202 #endif // DOXYGEN_NO_DETAIL
203 
204 }} // namespace boost::geometry
205 
206 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP
207