]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/test/algorithms/set_operations/intersection/test_intersection.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / set_operations / intersection / test_intersection.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2// Unit Test
3
4// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
5
b32b8144
FG
6// This file was modified by Oracle on 2016, 2017.
7// Modifications copyright (c) 2016-2017, Oracle and/or its affiliates.
7c673cae
FG
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_TEST_INTERSECTION_HPP
15#define BOOST_GEOMETRY_TEST_INTERSECTION_HPP
16
17#include <fstream>
18#include <iomanip>
19
20#include <boost/foreach.hpp>
21#include <boost/variant/variant.hpp>
22
23#include <boost/geometry/algorithms/intersection.hpp>
24#include <boost/geometry/algorithms/area.hpp>
25#include <boost/geometry/algorithms/correct.hpp>
26#include <boost/geometry/algorithms/is_valid.hpp>
27#include <boost/geometry/algorithms/length.hpp>
28#include <boost/geometry/algorithms/num_points.hpp>
29#include <boost/geometry/algorithms/num_interior_rings.hpp>
30
31#include <boost/geometry/geometries/geometries.hpp>
32
33#include <boost/geometry/strategies/strategies.hpp>
34
35#include <boost/geometry/io/wkt/wkt.hpp>
36
37
38#if defined(TEST_WITH_SVG)
39# include <boost/geometry/io/svg/svg_mapper.hpp>
40#endif
41
42#include <geometry_test_common.hpp>
43#include "../setop_output_type.hpp"
b32b8144 44#include "../check_validity.hpp"
7c673cae
FG
45
46struct ut_settings
47{
48 double percentage;
49 bool test_validity;
50 bool debug;
51
52 explicit ut_settings(double p = 0.0001, bool tv = true)
53 : percentage(p)
54 , test_validity(tv)
55 , debug(false)
56 {}
57
58};
59
b32b8144
FG
60template
61<
62 typename G1,
63 typename G2,
64 typename ResultType,
65 typename IntersectionOutput
66>
7c673cae
FG
67typename bg::default_area_result<G1>::type
68check_result(
69 IntersectionOutput const& intersection_output,
70 std::string const& caseid,
71 std::size_t expected_count, std::size_t expected_holes_count,
72 int expected_point_count, double expected_length_or_area,
73 ut_settings const& settings)
74{
75 typedef typename boost::range_value<IntersectionOutput>::type OutputType;
76 bool const is_line = bg::geometry_id<OutputType>::type::value == 2;
77
78 typename bg::default_area_result<G1>::type length_or_area = 0;
79 int n = 0;
80 std::size_t nholes = 0;
81 for (typename IntersectionOutput::const_iterator it = intersection_output.begin();
82 it != intersection_output.end();
83 ++it)
84 {
85 if (expected_point_count > 0)
86 {
87 // here n should rather be of type std::size_t, but expected_point_count
88 // is set to -1 in some test cases so type int was left for now
89 n += static_cast<int>(bg::num_points(*it, true));
90 }
91
92 if (expected_holes_count > 0)
93 {
94 nholes += bg::num_interior_rings(*it);
95 }
96
97 // instead of specialization we check it run-time here
98 length_or_area += is_line
99 ? bg::length(*it)
100 : bg::area(*it);
101
102 if (settings.debug)
103 {
104 std::cout << std::setprecision(20) << bg::wkt(*it) << std::endl;
105 }
b32b8144 106 }
7c673cae 107
b32b8144
FG
108 if (settings.test_validity)
109 {
110 std::string message;
111 bool const valid = check_validity<ResultType>::apply(intersection_output, message);
112 BOOST_CHECK_MESSAGE(valid,
113 "intersection: " << caseid << " not valid: " << message
114 << " type: " << (type_for_assert_message<G1, G2>()));
7c673cae
FG
115 }
116
117#if ! defined(BOOST_GEOMETRY_NO_BOOST_TEST)
118#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
119 if (expected_point_count > 0)
120 {
121 BOOST_CHECK_MESSAGE(bg::math::abs(n - expected_point_count) < 3,
122 "intersection: " << caseid
123 << " #points expected: " << expected_point_count
124 << " detected: " << n
125 << " type: " << (type_for_assert_message<G1, G2>())
126 );
127 }
128#endif
129
130 if (expected_count > 0)
131 {
132 BOOST_CHECK_MESSAGE(intersection_output.size() == expected_count,
133 "intersection: " << caseid
134 << " #outputs expected: " << expected_count
135 << " detected: " << intersection_output.size()
136 << " type: " << (type_for_assert_message<G1, G2>())
137 );
138 }
139
140 if (expected_holes_count > 0)
141 {
142
143 BOOST_CHECK_MESSAGE(nholes == expected_holes_count,
144 "intersection: " << caseid
145 << " #holes expected: " << expected_holes_count
146 << " detected: " << nholes
147 << " type: " << (type_for_assert_message<G1, G2>())
148 );
149 }
150
151 double const detected_length_or_area = boost::numeric_cast<double>(length_or_area);
152 if (settings.percentage > 0.0)
153 {
154 BOOST_CHECK_CLOSE(detected_length_or_area, expected_length_or_area, settings.percentage);
155 }
156 else
157 {
158 // In some cases (geos_2) the intersection is either 0, or a tiny rectangle,
159 // depending on compiler/settings. That cannot be tested by CLOSE
160 BOOST_CHECK_LE(detected_length_or_area, expected_length_or_area);
161 }
162#endif
163
164 return length_or_area;
165}
166
167
168template <typename OutputType, typename CalculationType, typename G1, typename G2>
169typename bg::default_area_result<G1>::type test_intersection(std::string const& caseid,
170 G1 const& g1, G2 const& g2,
171 std::size_t expected_count = 0, std::size_t expected_holes_count = 0,
172 int expected_point_count = 0, double expected_length_or_area = 0,
173 ut_settings const& settings = ut_settings())
174{
175 if (settings.debug)
176 {
177 std::cout << std::endl << "case " << caseid << std::endl;
178 }
179
7c673cae
FG
180 typedef typename setop_output_type<OutputType>::type result_type;
181
b32b8144
FG
182 typedef typename bg::point_type<G1>::type point_type;
183 boost::ignore_unused<point_type>();
184
185#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
7c673cae
FG
186 if (! settings.debug)
187 {
188 // Check _inserter behaviour with stratey
b32b8144 189 typedef typename bg::strategy::intersection::services::default_strategy
7c673cae 190 <
b32b8144
FG
191 typename bg::cs_tag<point_type>::type
192 >::type strategy_type;
7c673cae 193 result_type clip;
b32b8144 194 bg::detail::intersection::intersection_insert<OutputType>(g1, g2, std::back_inserter(clip), strategy_type());
7c673cae 195 }
b32b8144 196#endif
7c673cae
FG
197
198 typename bg::default_area_result<G1>::type length_or_area = 0;
199
200 // Check normal behaviour
201 result_type intersection_output;
202 bg::intersection(g1, g2, intersection_output);
203
b32b8144 204 check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
7c673cae
FG
205 expected_holes_count, expected_point_count, expected_length_or_area,
206 settings);
207
b32b8144 208#if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE)
7c673cae
FG
209 // Check variant behaviour
210 intersection_output.clear();
211 bg::intersection(boost::variant<G1>(g1), g2, intersection_output);
212
b32b8144 213 check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
7c673cae
FG
214 expected_holes_count, expected_point_count, expected_length_or_area,
215 settings);
216
217 intersection_output.clear();
218 bg::intersection(g1, boost::variant<G2>(g2), intersection_output);
219
b32b8144 220 check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
7c673cae
FG
221 expected_holes_count, expected_point_count, expected_length_or_area,
222 settings);
223
224 intersection_output.clear();
225 bg::intersection(boost::variant<G1>(g1), boost::variant<G2>(g2), intersection_output);
226
b32b8144 227 check_result<G1, G2, result_type>(intersection_output, caseid, expected_count,
7c673cae
FG
228 expected_holes_count, expected_point_count, expected_length_or_area,
229 settings);
b32b8144 230#endif
7c673cae
FG
231
232#if defined(TEST_WITH_SVG)
233 {
234 bool const is_line = bg::geometry_id<OutputType>::type::value == 2;
235 typedef typename bg::coordinate_type<G1>::type coordinate_type;
236
237 bool const ccw =
238 bg::point_order<G1>::value == bg::counterclockwise
239 || bg::point_order<G2>::value == bg::counterclockwise;
240 bool const open =
241 bg::closure<G1>::value == bg::open
242 || bg::closure<G2>::value == bg::open;
243
244 std::ostringstream filename;
245 filename << "intersection_"
246 << caseid << "_"
247 << string_from_type<coordinate_type>::name()
248 << string_from_type<CalculationType>::name()
249 << (ccw ? "_ccw" : "")
250 << (open ? "_open" : "")
b32b8144
FG
251#if defined(BOOST_GEOMETRY_INCLUDE_SELF_TURNS)
252 << "_self"
253#endif
7c673cae
FG
254#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
255 << "_no_rob"
256#endif
257 << ".svg";
258
259 std::ofstream svg(filename.str().c_str());
260
261 bg::svg_mapper<point_type> mapper(svg, 500, 500);
262
263 mapper.add(g1);
264 mapper.add(g2);
265
266 mapper.map(g1, is_line
267 ? "opacity:0.6;stroke:rgb(0,255,0);stroke-width:5"
268 : "fill-opacity:0.5;fill:rgb(153,204,0);"
269 "stroke:rgb(153,204,0);stroke-width:3");
270 mapper.map(g2, "fill-opacity:0.3;fill:rgb(51,51,153);"
271 "stroke:rgb(51,51,153);stroke-width:3");
272
273 for (typename result_type::const_iterator it = intersection_output.begin();
274 it != intersection_output.end(); ++it)
275 {
276 mapper.map(*it, "fill-opacity:0.2;stroke-opacity:0.4;fill:rgb(255,0,0);"
277 "stroke:rgb(255,0,255);stroke-width:8");
278 }
279 }
280#endif
281
282
283 if (settings.debug)
284 {
285 std::cout << "end case " << caseid << std::endl;
286 }
287
288 return length_or_area;
289}
290
291template <typename OutputType, typename CalculationType, typename G1, typename G2>
292typename bg::default_area_result<G1>::type test_intersection(std::string const& caseid,
293 G1 const& g1, G2 const& g2,
294 std::size_t expected_count = 0, int expected_point_count = 0,
295 double expected_length_or_area = 0,
296 ut_settings const& settings = ut_settings())
297{
298 return test_intersection<OutputType, CalculationType>(
299 caseid, g1, g2, expected_count, 0, expected_point_count,
300 expected_length_or_area, settings
301 );
302}
303
304template <typename OutputType, typename G1, typename G2>
305typename bg::default_area_result<G1>::type test_one(std::string const& caseid,
306 std::string const& wkt1, std::string const& wkt2,
307 std::size_t expected_count = 0, std::size_t expected_holes_count = 0,
308 int expected_point_count = 0, double expected_length_or_area = 0,
309 ut_settings const& settings = ut_settings())
310{
311 G1 g1;
312 bg::read_wkt(wkt1, g1);
313
314 G2 g2;
315 bg::read_wkt(wkt2, g2);
316
317 // Reverse if necessary
318 bg::correct(g1);
319 bg::correct(g2);
320
321 return test_intersection<OutputType, void>(caseid, g1, g2,
322 expected_count, expected_holes_count, expected_point_count,
323 expected_length_or_area, settings);
324}
325
326template <typename OutputType, typename G1, typename G2>
327typename bg::default_area_result<G1>::type test_one(std::string const& caseid,
328 std::string const& wkt1, std::string const& wkt2,
329 std::size_t expected_count = 0, int expected_point_count = 0,
330 double expected_length_or_area = 0,
331 ut_settings const& settings = ut_settings())
332{
333 return test_one<OutputType, G1, G2>(caseid, wkt1, wkt2,
334 expected_count, 0, expected_point_count,
335 expected_length_or_area,
336 settings);
337}
338
339template <typename OutputType, typename Areal, typename Linear>
340void test_one_lp(std::string const& caseid,
341 std::string const& wkt_areal, std::string const& wkt_linear,
342 std::size_t expected_count = 0, int expected_point_count = 0,
343 double expected_length = 0,
344 ut_settings const& settings = ut_settings())
345{
346#ifdef BOOST_GEOMETRY_TEST_DEBUG
347 std::cout << caseid << " -- start" << std::endl;
348#endif
349 Areal areal;
350 bg::read_wkt(wkt_areal, areal);
351 bg::correct(areal);
352
353 Linear linear;
354 bg::read_wkt(wkt_linear, linear);
355
356 test_intersection<OutputType, void>(caseid, areal, linear,
357 expected_count, expected_point_count,
358 expected_length, settings);
359
360 // A linestring reversed should deliver exactly the same.
361 bg::reverse(linear);
362
363 test_intersection<OutputType, void>(caseid + "_rev", areal, linear,
364 expected_count, expected_point_count,
365 expected_length, settings);
366#ifdef BOOST_GEOMETRY_TEST_DEBUG
367 std::cout << caseid << " -- end" << std::endl;
368#endif
369}
370
371template <typename Geometry1, typename Geometry2>
372void test_point_output(std::string const& wkt1, std::string const& wkt2, unsigned int expected_count)
373{
374 Geometry1 g1;
375 bg::read_wkt(wkt1, g1);
376 bg::correct(g1);
377
378 Geometry2 g2;
379 bg::read_wkt(wkt2, g2);
380 bg::correct(g2);
381
382 bg::model::multi_point<typename bg::point_type<Geometry1>::type> points;
383 bg::intersection(g1, g2, points);
384 BOOST_CHECK_EQUAL(points.size(), expected_count);
385}
386
387
388#endif