]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/test/robustness/overlay/areal_areal/test_overlay_p_q.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / geometry / test / robustness / overlay / areal_areal / test_overlay_p_q.hpp
CommitLineData
7c673cae 1// Boost.Geometry (aka GGL, Generic Geometry Library)
20effc67 2// Robustness Test
1e59de90
TL
3
4// Copyright (c) 2009-2021 Barend Gehrels, Amsterdam, the Netherlands.
5
6// This file was modified by Oracle on 2021.
7// Modifications copyright (c) 2021, Oracle and/or its affiliates.
8// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9
7c673cae
FG
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_OVERLAY_P_Q_HPP
15#define BOOST_GEOMETRY_TEST_OVERLAY_P_Q_HPP
16
b32b8144 17#include <iostream>
7c673cae
FG
18#include <fstream>
19#include <sstream>
20#include <iomanip>
21
7c673cae
FG
22#include <geometry_test_common.hpp>
23
24// For mixing int/float
25#if defined(_MSC_VER)
26#pragma warning( disable : 4244 )
27#pragma warning( disable : 4267 )
28#endif
29
30
31#include <boost/geometry.hpp>
32#include <boost/geometry/geometries/geometries.hpp>
33#include <boost/geometry/geometries/point_xy.hpp>
34#include <boost/geometry/io/svg/svg_mapper.hpp>
35
36#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
37#include <boost/geometry/algorithms/intersects.hpp>
b32b8144 38#include <boost/geometry/algorithms/is_valid.hpp>
7c673cae
FG
39#include <boost/geometry/algorithms/touches.hpp>
40
41struct p_q_settings
42{
1e59de90
TL
43 bool svg{false};
44 bool also_difference{false};
45 bool validity{false};
46 bool wkt{false};
47 bool verify_area{false};
48 double tolerance{1.0e-3};
49 bool verbose{false};
50
51 // NOTE: since rescaling to integer the tolerance is less.
52 // Was originally 1.0e-6 TODO: restore
7c673cae
FG
53};
54
55template <typename Geometry>
56inline typename bg::default_area_result<Geometry>::type p_q_area(Geometry const& g)
57{
58 try
59 {
60 return bg::area(g);
61 }
62 catch(bg::empty_input_exception const&)
63 {
64 return 0;
65 }
66}
67
b32b8144
FG
68struct verify_area
69{
70 template <typename Iterator>
71 static inline bool check_ring(Iterator begin, Iterator end)
72 {
73 for (Iterator it = begin; it != end; ++it)
74 {
20effc67
TL
75 auto const area = bg::area(*it);
76 if (bg::math::abs(area) < 0.01)
b32b8144
FG
77 {
78 return false;
79 }
80 }
81 return true;
82 }
83
84 template <typename Interiors>
85 static inline bool check_rings(Interiors const& rings)
86 {
87 return check_ring(boost::begin(rings), boost::end(rings));
88 }
89
90 template <typename Iterator>
91 static inline bool check_polys(Iterator begin, Iterator end)
92 {
93 for (Iterator it = begin; it != end; ++it)
94 {
95 // If necessary, exterior_ring can be checked too
96 if (! check_rings(bg::interior_rings(*it)))
97 {
98 return false;
99 }
100 }
101 return true;
102 }
103
104 template <typename Geometry>
105 static inline bool apply(Geometry const& g)
106 {
107 return check_polys(boost::begin(g), boost::end(g));
108 }
109};
110
7c673cae
FG
111template <typename OutputType, typename CalculationType, typename G1, typename G2>
112static bool test_overlay_p_q(std::string const& caseid,
113 G1 const& p, G2 const& q,
114 p_q_settings const& settings)
115{
116 bool result = true;
117
118 typedef typename bg::coordinate_type<G1>::type coordinate_type;
119 typedef typename bg::point_type<G1>::type point_type;
120
b32b8144 121 bg::model::multi_polygon<OutputType> out_i, out_u, out_d1, out_d2;
7c673cae
FG
122
123 CalculationType area_p = p_q_area(p);
124 CalculationType area_q = p_q_area(q);
125 CalculationType area_d1 = 0, area_d2 = 0;
126
127 bg::intersection(p, q, out_i);
128 CalculationType area_i = p_q_area(out_i);
129
130 bg::union_(p, q, out_u);
131 CalculationType area_u = p_q_area(out_u);
132
20effc67 133 auto const sum = (area_p + area_q) - area_u - area_i;
7c673cae 134
20effc67 135 bool wrong = bg::math::abs(sum) > settings.tolerance;
7c673cae
FG
136
137 if (settings.also_difference)
138 {
b32b8144 139 bg::difference(p, q, out_d1);
7c673cae 140 bg::difference(q, p, out_d2);
b32b8144 141 area_d1 = p_q_area(out_d1);
7c673cae 142 area_d2 = p_q_area(out_d2);
20effc67
TL
143 auto sum_d1 = (area_u - area_q) - area_d1;
144 auto sum_d2 = (area_u - area_p) - area_d2;
145 bool wrong_d1 = bg::math::abs(sum_d1) > settings.tolerance;
146 bool wrong_d2 = bg::math::abs(sum_d2) > settings.tolerance;
7c673cae
FG
147
148 if (wrong_d1 || wrong_d2)
149 {
150 wrong = true;
151 }
152 }
153
b32b8144
FG
154 if (settings.validity)
155 {
156 std::string message;
157 if (! bg::is_valid(out_u, message))
158 {
159 std::cout << "Union is not valid: " << message << std::endl;
160 wrong = true;
161 }
162 if (! bg::is_valid(out_i, message))
163 {
164 std::cout << "Intersection is not valid: " << message << std::endl;
165 wrong = true;
166 }
167 if (settings.also_difference)
168 {
169 if (! bg::is_valid(out_d1, message))
170 {
171 std::cout << "Difference (p-q) is not valid: " << message << std::endl;
172 wrong = true;
173 }
174 if (! bg::is_valid(out_d2, message))
175 {
176 std::cout << "Difference (q-p) is not valid: " << message << std::endl;
177 wrong = true;
178 }
179 }
180
181 if (settings.verify_area && ! verify_area::apply(out_u))
182 {
183 std::cout << "Union/interior area incorrect" << std::endl;
184 wrong = true;
185 }
186 if (settings.verify_area && ! verify_area::apply(out_i))
187 {
188 std::cout << "Intersection/interior area incorrect" << std::endl;
189 wrong = true;
190 }
191 }
192
7c673cae
FG
193 if (true)
194 {
195 if ((area_i > 0 && bg::touches(p, q))
196 || (area_i <= 0 && bg::intersects(p, q) && ! bg::touches(p, q)))
197 {
198 std::cout << "Wrong 'touch'! "
199 << " Intersection area: " << area_i
200 << " Touch gives: " << std::boolalpha << bg::touches(p, q)
201 << std::endl;
202 wrong = true;
203 }
204 }
205
206 bool svg = settings.svg;
1e59de90 207 bool wkt = settings.wkt;
7c673cae
FG
208
209 if (wrong || settings.wkt)
210 {
211 if (wrong)
212 {
213 result = false;
214 svg = true;
1e59de90 215 wkt = true;
7c673cae 216 }
7c673cae 217
1e59de90 218 if (settings.verbose)
7c673cae
FG
219 {
220 std::cout
1e59de90
TL
221 << "type: " << string_from_type<CalculationType>::name()
222 << " id: " << caseid
223 << " area i: " << area_i
224 << " area u: " << area_u
225 << " area p: " << area_p
226 << " area q: " << area_q
227 << " sum: " << sum;
228
229 if (settings.also_difference)
230 {
231 std::cout
232 << " area d1: " << area_d1
233 << " area d2: " << area_d2;
234 }
235 std::cout
236 << std::endl
237 << std::setprecision(9)
238 << " p: " << bg::wkt(p) << std::endl
239 << " q: " << bg::wkt(q) << std::endl
240 << " i: " << bg::wkt(out_i) << std::endl
241 << " u: " << bg::wkt(out_u) << std::endl;
7c673cae 242 }
7c673cae
FG
243 }
244
1e59de90 245 std::string filename;
7c673cae 246 {
1e59de90
TL
247 std::ostringstream out;
248 out << "overlay_" << caseid << "_"
20effc67
TL
249 << string_from_type<coordinate_type>::name();
250 if (!std::is_same<coordinate_type, CalculationType>::value)
251 {
1e59de90 252 out << string_from_type<CalculationType>::name();
20effc67 253 }
1e59de90 254 out
20effc67 255#if defined(BOOST_GEOMETRY_USE_RESCALING)
1e59de90 256 << "_rescaled"
20effc67 257#endif
1e59de90
TL
258 << ".";
259 filename = out.str();
260 }
261
262 if (wkt)
263 {
264 std::ofstream stream(filename + "wkt");
265 // Stream input WKT's
266 stream << bg::wkt(p) << std::endl;
267 stream << bg::wkt(q) << std::endl;
268 // If you need the output WKT, then stream out_i and out_u
269 }
7c673cae 270
1e59de90
TL
271
272 if (svg)
273 {
274 std::ofstream svg(filename + "svg");
7c673cae
FG
275
276 bg::svg_mapper<point_type> mapper(svg, 500, 500);
277
278 mapper.add(p);
279 mapper.add(q);
280
281 // Input shapes in green/blue
282 mapper.map(p, "fill-opacity:0.5;fill:rgb(153,204,0);"
283 "stroke:rgb(153,204,0);stroke-width:3");
284 mapper.map(q, "fill-opacity:0.3;fill:rgb(51,51,153);"
285 "stroke:rgb(51,51,153);stroke-width:3");
286
287 if (settings.also_difference)
288 {
1e59de90 289 for (auto it = out_d1.begin(); it != out_d1.end(); ++it)
7c673cae
FG
290 {
291 mapper.map(*it,
292 "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
293 }
1e59de90 294 for (auto it = out_d2.begin(); it != out_d2.end(); ++it)
7c673cae
FG
295 {
296 mapper.map(*it,
297 "opacity:0.8;fill:none;stroke:rgb(255,0,255);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
298 }
299 }
300 else
301 {
b32b8144
FG
302 mapper.map(out_i, "fill-opacity:0.1;stroke-opacity:0.4;fill:rgb(255,0,128);"
303 "stroke:rgb(255,0,0);stroke-width:4");
304 mapper.map(out_u, "fill-opacity:0.1;stroke-opacity:0.4;fill:rgb(255,0,0);"
305 "stroke:rgb(255,0,255);stroke-width:4");
7c673cae
FG
306 }
307 }
308 return result;
309}
310
311#endif // BOOST_GEOMETRY_TEST_OVERLAY_P_Q_HPP