]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
1e59de90 | 3 | // Copyright (c) 2014-2021, Oracle and/or its affiliates. |
b32b8144 FG |
4 | // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle |
5 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
7c673cae FG |
6 | |
7 | // Licensed under the Boost Software License version 1.0. | |
8 | // http://www.boost.org/users/license.html | |
9 | ||
7c673cae FG |
10 | |
11 | #ifndef BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP | |
12 | #define BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP | |
13 | ||
14 | #include <limits> | |
15 | ||
1e59de90 | 16 | #include <boost/range/value_type.hpp> |
7c673cae FG |
17 | |
18 | #include <boost/geometry/geometry.hpp> | |
19 | #include "../test_set_ops_linear_linear.hpp" | |
1e59de90 | 20 | #include "../alternative_robustness_strategy.hpp" |
7c673cae FG |
21 | #include <from_wkt.hpp> |
22 | #include <to_svg.hpp> | |
23 | ||
24 | ||
1e59de90 TL |
25 | //! Contains (optional) settings such as tolerance |
26 | //! and to skip some test configurations | |
27 | struct ut_settings | |
28 | { | |
29 | ut_settings() = default; | |
30 | ||
31 | // Make it backwards compatible by a non-explicit constructor | |
32 | // such that just tolerance is also accepted | |
33 | ut_settings(const double t) : tolerance(t) {} | |
34 | ||
35 | double tolerance{std::numeric_limits<double>::epsilon()}; | |
36 | ||
37 | // By default everything is tested. | |
38 | // Some rare cases might fail for some strategies, in that case | |
39 | // some strategies can be turned off | |
40 | bool test_invariance{true}; | |
41 | bool test_reverse{true}; | |
42 | ||
43 | bool test_default_strategy{true}; | |
44 | bool test_explicit_strategy{true}; | |
45 | bool test_alternative_side_strategy{true}; | |
46 | }; | |
47 | ||
7c673cae FG |
48 | //================================================================== |
49 | //================================================================== | |
50 | // intersection of (linear) geometries | |
51 | //================================================================== | |
52 | //================================================================== | |
53 | ||
1e59de90 | 54 | |
b32b8144 FG |
55 | template <typename Geometry1, typename Geometry2, typename MultiLineString> |
56 | inline void check_result(Geometry1 const& geometry1, | |
57 | Geometry2 const& geometry2, | |
58 | MultiLineString const& mls_output, | |
59 | MultiLineString const& mls_int1, | |
60 | MultiLineString const& mls_int2, | |
61 | std::string const& case_id, | |
62 | double tolerance) | |
63 | { | |
64 | BOOST_CHECK_MESSAGE( equals::apply(mls_int1, mls_output, tolerance) | |
65 | || equals::apply(mls_int2, mls_output, tolerance), | |
66 | "case id: " << case_id | |
1e59de90 TL |
67 | << " Expected: len=" << bg::length(mls_int1) << " count=" << bg::num_points(mls_int1) |
68 | << " or: len=" << bg::length(mls_int2) << " count=" << bg::num_points(mls_int2) | |
69 | << " Detected: len=" << bg::length(mls_output) << " count=" << bg::num_points(mls_output) | |
70 | << " wkt=" << std::setprecision(12) << bg::wkt(mls_output) | |
71 | ); | |
b32b8144 FG |
72 | } |
73 | ||
7c673cae FG |
74 | template |
75 | < | |
76 | typename Geometry1, typename Geometry2, | |
77 | typename MultiLineString | |
78 | > | |
79 | class test_intersection_of_geometries | |
80 | { | |
81 | private: | |
82 | static inline void base_test(Geometry1 const& geometry1, | |
83 | Geometry2 const& geometry2, | |
84 | MultiLineString const& mls_int1, | |
85 | MultiLineString const& mls_int2, | |
86 | std::string const& case_id, | |
1e59de90 | 87 | ut_settings const& settings, |
7c673cae FG |
88 | bool test_vector_and_deque = false) |
89 | { | |
90 | static bool vector_deque_already_tested = false; | |
91 | ||
92 | typedef typename boost::range_value<MultiLineString>::type LineString; | |
7c673cae | 93 | |
1e59de90 TL |
94 | if (settings.test_default_strategy) |
95 | { | |
96 | MultiLineString mls_output; | |
97 | bg::intersection(geometry1, geometry2, mls_output); | |
7c673cae | 98 | |
1e59de90 TL |
99 | check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, |
100 | case_id, settings.tolerance); | |
7c673cae | 101 | |
1e59de90 TL |
102 | #ifdef TEST_WITH_SVG |
103 | to_svg(geometry1, geometry2, mls_output, case_id); | |
104 | set_operation_output("intersection", case_id, | |
105 | geometry1, geometry2, mls_output); | |
106 | #endif | |
107 | #ifdef BOOST_GEOMETRY_TEST_DEBUG | |
108 | std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl; | |
109 | std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl; | |
110 | std::cout << "intersection : " << bg::wkt(mls_output) << std::endl; | |
111 | std::cout << "expected intersection : " << bg::wkt(mls_int1) | |
112 | << " or: " << bg::wkt(mls_int2) << std::endl; | |
113 | std::cout << std::endl; | |
114 | std::cout << "************************************" << std::endl; | |
115 | std::cout << std::endl; | |
116 | std::cout << std::endl; | |
117 | #endif | |
118 | } | |
7c673cae | 119 | |
1e59de90 TL |
120 | if (settings.test_explicit_strategy) |
121 | { | |
122 | MultiLineString mls_output; | |
123 | using strategy_type | |
124 | = typename bg::strategy::relate::services::default_strategy | |
125 | < | |
126 | Geometry1, Geometry2 | |
127 | >::type ; | |
128 | bg::intersection(geometry1, geometry2, mls_output, strategy_type()); | |
b32b8144 | 129 | |
1e59de90 TL |
130 | #ifdef TEST_WITH_SVG |
131 | to_svg(geometry1, geometry2, mls_output, case_id + "_explicit"); | |
132 | #endif | |
b32b8144 | 133 | |
1e59de90 TL |
134 | check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, |
135 | case_id, settings.tolerance); | |
136 | } | |
7c673cae | 137 | |
1e59de90 TL |
138 | if (settings.test_alternative_side_strategy) |
139 | { | |
140 | using side_strategy_type = bg::strategy::side::side_robust<>; | |
141 | ||
142 | MultiLineString mls_output; | |
143 | bg::intersection(geometry1, geometry2, mls_output, | |
144 | alternative_robustness_strategy<side_strategy_type>()); | |
145 | ||
146 | #ifdef TEST_WITH_SVG | |
147 | to_svg(geometry1, geometry2, mls_output, case_id + "_alternative"); | |
7c673cae FG |
148 | #endif |
149 | ||
1e59de90 TL |
150 | check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, |
151 | case_id, settings.tolerance); | |
152 | } | |
153 | ||
154 | if (! vector_deque_already_tested && test_vector_and_deque) | |
7c673cae FG |
155 | { |
156 | vector_deque_already_tested = true; | |
1e59de90 TL |
157 | |
158 | typedef std::vector<LineString> linestring_vector; | |
159 | typedef std::deque<LineString> linestring_deque; | |
160 | linestring_vector ls_vector_output; | |
161 | linestring_deque ls_deque_output; | |
162 | ||
7c673cae FG |
163 | #ifdef BOOST_GEOMETRY_TEST_DEBUG |
164 | std::cout << std::endl; | |
165 | std::cout << "Testing with vector and deque as output container..." | |
166 | << std::endl; | |
167 | #endif | |
168 | bg::intersection(geometry1, geometry2, ls_vector_output); | |
169 | bg::intersection(geometry1, geometry2, ls_deque_output); | |
170 | ||
171 | BOOST_CHECK(multilinestring_equals | |
172 | < | |
173 | false | |
1e59de90 | 174 | >::apply(mls_int1, ls_vector_output, settings.tolerance)); |
7c673cae FG |
175 | |
176 | BOOST_CHECK(multilinestring_equals | |
177 | < | |
178 | false | |
1e59de90 | 179 | >::apply(mls_int1, ls_deque_output, settings.tolerance)); |
7c673cae FG |
180 | |
181 | #ifdef BOOST_GEOMETRY_TEST_DEBUG | |
182 | std::cout << "Done!" << std::endl << std::endl; | |
183 | #endif | |
184 | } | |
185 | ||
1e59de90 TL |
186 | if (settings.test_reverse) |
187 | { | |
188 | // check the intersection where the order of the two | |
189 | // geometries is reversed | |
190 | MultiLineString mls_output; | |
191 | bg::intersection(geometry2, geometry1, mls_output); | |
7c673cae | 192 | |
1e59de90 TL |
193 | check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, |
194 | case_id, settings.tolerance); | |
195 | } | |
7c673cae FG |
196 | } |
197 | ||
198 | #ifdef BOOST_GEOMETRY_TEST_DEBUG | |
199 | static inline void base_test_all(Geometry1 const& geometry1, | |
200 | Geometry2 const& geometry2) | |
201 | { | |
202 | typedef typename bg::point_type<MultiLineString>::type Point; | |
203 | typedef bg::model::multi_point<Point> multi_point; | |
204 | ||
205 | MultiLineString mls12_output, mls21_output; | |
206 | multi_point mp12_output, mp21_output; | |
207 | ||
208 | bg::intersection(geometry1, geometry2, mls12_output); | |
209 | bg::intersection(geometry1, geometry2, mp12_output); | |
210 | bg::intersection(geometry2, geometry1, mls21_output); | |
211 | bg::intersection(geometry2, geometry1, mp21_output); | |
212 | ||
213 | std::cout << "************************************" << std::endl; | |
214 | std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl; | |
215 | std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl; | |
216 | std::cout << "intersection(1,2) [MLS]: " << bg::wkt(mls12_output) | |
217 | << std::endl; | |
218 | std::cout << "intersection(2,1) [MLS]: " << bg::wkt(mls21_output) | |
219 | << std::endl; | |
220 | std::cout << std::endl; | |
221 | std::cout << "intersection(1,2) [MP]: " << bg::wkt(mp12_output) | |
222 | << std::endl; | |
223 | std::cout << "intersection(2,1) [MP]: " << bg::wkt(mp21_output) | |
224 | << std::endl; | |
225 | std::cout << std::endl; | |
226 | std::cout << "************************************" << std::endl; | |
227 | std::cout << std::endl; | |
228 | std::cout << std::endl; | |
229 | } | |
230 | #else | |
231 | static inline void base_test_all(Geometry1 const&, Geometry2 const&) | |
232 | { | |
233 | } | |
234 | #endif | |
235 | ||
236 | ||
237 | public: | |
238 | static inline void apply(Geometry1 const& geometry1, | |
239 | Geometry2 const& geometry2, | |
240 | MultiLineString const& mls_int1, | |
241 | MultiLineString const& mls_int2, | |
242 | std::string const& case_id, | |
1e59de90 | 243 | ut_settings const& settings = ut_settings()) |
7c673cae FG |
244 | { |
245 | #ifdef BOOST_GEOMETRY_TEST_DEBUG | |
246 | std::cout << "test case: " << case_id << std::endl; | |
7c673cae | 247 | #endif |
1e59de90 TL |
248 | BOOST_CHECK(settings.test_default_strategy |
249 | || settings.test_explicit_strategy | |
250 | || settings.test_alternative_side_strategy); | |
7c673cae FG |
251 | |
252 | Geometry1 rg1(geometry1); | |
253 | bg::reverse<Geometry1>(rg1); | |
254 | ||
255 | Geometry2 rg2(geometry2); | |
256 | bg::reverse<Geometry2>(rg2); | |
257 | ||
1e59de90 TL |
258 | if (settings.test_invariance) |
259 | { | |
260 | static const bool linear = bg::util::is_linear<Geometry1>::value | |
261 | && bg::util::is_linear<Geometry2>::value; | |
7c673cae | 262 | |
1e59de90 | 263 | test_get_turns_ll_invariance<linear>::apply(geometry1, geometry2); |
7c673cae | 264 | #ifdef BOOST_GEOMETRY_TEST_DEBUG |
1e59de90 TL |
265 | std::cout << std::endl |
266 | << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" | |
267 | << std::endl << std::endl; | |
7c673cae | 268 | #endif |
1e59de90 TL |
269 | test_get_turns_ll_invariance<linear>::apply(rg1, geometry2); |
270 | } | |
7c673cae | 271 | |
1e59de90 | 272 | base_test(geometry1, geometry2, mls_int1, mls_int2, case_id, settings); |
7c673cae FG |
273 | base_test_all(geometry1, geometry2); |
274 | ||
275 | #ifdef BOOST_GEOMETRY_TEST_DEBUG | |
276 | std::cout << std::endl; | |
277 | std::cout << std::endl; | |
278 | #endif | |
279 | } | |
280 | ||
281 | ||
282 | ||
283 | static inline void apply(Geometry1 const& geometry1, | |
284 | Geometry2 const& geometry2, | |
285 | MultiLineString const& mls_int, | |
286 | std::string const& case_id, | |
1e59de90 | 287 | ut_settings const& settings = ut_settings()) |
7c673cae | 288 | { |
1e59de90 | 289 | apply(geometry1, geometry2, mls_int, mls_int, case_id, settings); |
7c673cae FG |
290 | } |
291 | }; | |
292 | ||
293 | ||
294 | #endif // BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP |