1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
6 // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
7
8 // This file was modified by Oracle on 2013-2019.
9 // Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
10
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
12 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
13
14 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
15 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16
17 // Use, modification and distribution is subject to the Boost Software License,
18 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
19 // http://www.boost.org/LICENSE_1_0.txt)
20
21 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
22 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
23
24 #include <boost/geometry/core/point_type.hpp>
25
26 #include <boost/geometry/algorithms/covered_by.hpp>
27 #include <boost/geometry/algorithms/detail/for_each_range.hpp>
28 #include <boost/geometry/algorithms/detail/point_on_border.hpp>
29
30 #include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
31 #include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
32
33 #include <boost/geometry/iterators/segment_iterator.hpp>
34
35
36 namespace boost { namespace geometry
37 {
38
39
40 #ifndef DOXYGEN_NO_DETAIL
41 namespace detail { namespace disjoint
42 {
43
44 template <typename Geometry1, typename Geometry2, typename Strategy>
point_on_border_covered_by(Geometry1 const & geometry1,Geometry2 const & geometry2,Strategy const & strategy)45 inline bool point_on_border_covered_by(Geometry1 const& geometry1,
46 Geometry2 const& geometry2,
47 Strategy const& strategy)
48 {
49 typename geometry::point_type<Geometry1>::type pt;
50 return geometry::point_on_border(pt, geometry1)
51 && geometry::covered_by(pt, geometry2, strategy);
52 }
53
54 /*!
55 \tparam Strategy point_in_geometry strategy
56 */
57 template<typename Geometry, typename Strategy>
58 struct check_each_ring_for_within
59 {
60 bool not_disjoint;
61 Geometry const& m_geometry;
62 Strategy const& m_strategy;
63
check_each_ring_for_withinboost::geometry::detail::disjoint::check_each_ring_for_within64 inline check_each_ring_for_within(Geometry const& g,
65 Strategy const& strategy)
66 : not_disjoint(false)
67 , m_geometry(g)
68 , m_strategy(strategy)
69 {}
70
71 template <typename Range>
applyboost::geometry::detail::disjoint::check_each_ring_for_within72 inline void apply(Range const& range)
73 {
74 not_disjoint = not_disjoint
75 || point_on_border_covered_by(range, m_geometry, m_strategy);
76 }
77 };
78
79
80 /*!
81 \tparam Strategy point_in_geometry strategy
82 */
83 template <typename FirstGeometry, typename SecondGeometry, typename Strategy>
rings_containing(FirstGeometry const & geometry1,SecondGeometry const & geometry2,Strategy const & strategy)84 inline bool rings_containing(FirstGeometry const& geometry1,
85 SecondGeometry const& geometry2,
86 Strategy const& strategy)
87 {
88 check_each_ring_for_within
89 <
90 FirstGeometry, Strategy
91 > checker(geometry1, strategy);
92 geometry::detail::for_each_range(geometry2, checker);
93 return checker.not_disjoint;
94 }
95
96
97
98 template <typename Geometry1, typename Geometry2>
99 struct areal_areal
100 {
101 /*!
102 \tparam Strategy relate (segments intersection) strategy
103 */
104 template <typename Strategy>
applyboost::geometry::detail::disjoint::areal_areal105 static inline bool apply(Geometry1 const& geometry1,
106 Geometry2 const& geometry2,
107 Strategy const& strategy)
108 {
109 if ( ! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy) )
110 {
111 return false;
112 }
113
114 // If there is no intersection of segments, they might located
115 // inside each other
116
117 // We check that using a point on the border (external boundary),
118 // and see if that is contained in the other geometry. And vice versa.
119
120 if ( rings_containing(geometry1, geometry2,
121 strategy.template get_point_in_geometry_strategy<Geometry2, Geometry1>())
122 || rings_containing(geometry2, geometry1,
123 strategy.template get_point_in_geometry_strategy<Geometry1, Geometry2>()) )
124 {
125 return false;
126 }
127
128 return true;
129 }
130 };
131
132
133 template <typename Areal, typename Box>
134 struct areal_box
135 {
136 /*!
137 \tparam Strategy relate (segments intersection) strategy
138 */
139 template <typename Strategy>
applyboost::geometry::detail::disjoint::areal_box140 static inline bool apply(Areal const& areal,
141 Box const& box,
142 Strategy const& strategy)
143 {
144 if ( ! for_each_segment(geometry::segments_begin(areal),
145 geometry::segments_end(areal),
146 box,
147 strategy.get_disjoint_segment_box_strategy()) )
148 {
149 return false;
150 }
151
152 // If there is no intersection of any segment and box,
153 // the box might be located inside areal geometry
154
155 if ( point_on_border_covered_by(box, areal,
156 strategy.template get_point_in_geometry_strategy<Box, Areal>()) )
157 {
158 return false;
159 }
160
161 return true;
162 }
163
164 private:
165 template <typename SegIter, typename Strategy>
for_each_segmentboost::geometry::detail::disjoint::areal_box166 static inline bool for_each_segment(SegIter first,
167 SegIter last,
168 Box const& box,
169 Strategy const& strategy)
170 {
171 for ( ; first != last ; ++first)
172 {
173 if (! disjoint_segment_box::apply(*first, box, strategy))
174 {
175 return false;
176 }
177 }
178 return true;
179 }
180 };
181
182
183 }} // namespace detail::disjoint
184 #endif // DOXYGEN_NO_DETAIL
185
186
187
188
189 #ifndef DOXYGEN_NO_DISPATCH
190 namespace dispatch
191 {
192
193
194 template <typename Areal1, typename Areal2>
195 struct disjoint<Areal1, Areal2, 2, areal_tag, areal_tag, false>
196 : detail::disjoint::areal_areal<Areal1, Areal2>
197 {};
198
199
200 template <typename Areal, typename Box>
201 struct disjoint<Areal, Box, 2, areal_tag, box_tag, false>
202 : detail::disjoint::areal_box<Areal, Box>
203 {};
204
205
206 } // namespace dispatch
207 #endif // DOXYGEN_NO_DISPATCH
208
209
210 }} // namespace boost::geometry
211
212
213 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_AREAL_AREAL_HPP
214