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