]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/test/algorithms/overlay/sort_by_side_basic.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / overlay / sort_by_side_basic.cpp
CommitLineData
b32b8144
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2// Unit Test
3
4// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
11fdf7f2 5// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
b32b8144 6
1e59de90
TL
7// This file was modified by Oracle on 2017-2021.
8// Modifications copyright (c) 2017-2021, Oracle and/or its affiliates.
b32b8144
FG
9// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10
11// Use, modification and distribution is subject to the Boost Software License,
12// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13// http://www.boost.org/LICENSE_1_0.txt)
14
15#include <geometry_test_common.hpp>
16
1e59de90 17#include <boost/geometry/algorithms/correct.hpp>
b32b8144
FG
18#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
19#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
1e59de90 20#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
b32b8144 21#include <boost/geometry/algorithms/equals.hpp>
b32b8144 22#include <boost/geometry/geometries/geometries.hpp>
1e59de90 23#include <boost/geometry/io/wkt/wkt.hpp>
b32b8144
FG
24
25#if defined(TEST_WITH_SVG)
26#include "debug_sort_by_side_svg.hpp"
27#endif
28
29namespace
30{
31
32
33template <typename T>
34std::string as_string(std::vector<T> const& v)
35{
36 std::stringstream out;
37 bool first = true;
1e59de90 38 for (T const& value : v)
b32b8144
FG
39 {
40 out << (first ? "[" : " , ") << value;
41 first = false;
42 }
43 out << (first ? "" : "]");
44 return out.str();
45}
46
47}
48
49template
50<
51 typename Geometry, typename Point,
52 typename RobustPolicy, typename Strategy
53>
54std::vector<std::size_t> apply_get_turns(std::string const& case_id,
55 Geometry const& geometry1, Geometry const& geometry2,
56 Point const& turn_point, Point const& origin_point,
57 RobustPolicy const& robust_policy,
58 Strategy const& strategy,
59 std::size_t expected_open_count,
60 std::size_t expected_max_rank,
11fdf7f2 61 std::vector<bg::signed_size_type> const& expected_right_count)
b32b8144
FG
62{
63 using namespace boost::geometry;
64
65 std::vector<std::size_t> result;
66
67//todo: maybe should be enriched to count left/right - but can also be counted from ranks
68 typedef typename bg::point_type<Geometry>::type point_type;
69 typedef bg::detail::overlay::turn_info
70 <
71 point_type,
92f5a8d4 72 typename bg::detail::segment_ratio_type<point_type, RobustPolicy>::type
b32b8144
FG
73 > turn_info;
74 typedef std::deque<turn_info> turn_container_type;
75
76 turn_container_type turns;
77
78 detail::get_turns::no_interrupt_policy policy;
79 bg::get_turns
80 <
81 false, false,
82 detail::overlay::assign_null_policy
83 >(geometry1, geometry2, strategy, robust_policy, turns, policy);
84
85
86 // Define sorter, sorting counter-clockwise such that polygons are on the
87 // right side
1e59de90 88 typedef decltype(strategy.side()) side_strategy;
b32b8144
FG
89 typedef bg::detail::overlay::sort_by_side::side_sorter
90 <
91 false, false, overlay_union,
92 point_type, side_strategy, std::less<int>
93 > sbs_type;
94
1e59de90 95 sbs_type sbs(strategy.side());
b32b8144
FG
96
97 std::cout << "Case: " << case_id << std::endl;
98
99 bool has_origin = false;
100 for (std::size_t turn_index = 0; turn_index < turns.size(); turn_index++)
101 {
102 turn_info const& turn = turns[turn_index];
103
104 if (bg::equals(turn.point, turn_point))
105 {
106// std::cout << "Found turn: " << turn_index << std::endl;
107 for (int i = 0; i < 2; i++)
108 {
109 Point point1, point2, point3;
110 bg::copy_segment_points<false, false>(geometry1, geometry2,
111 turn.operations[i].seg_id, point1, point2, point3);
112 bool const is_origin = ! has_origin && bg::equals(point1, origin_point);
113 if (is_origin)
114 {
115 has_origin = true;
116 }
117
1e59de90 118 sbs.add(turn, turn.operations[i], turn_index, i,
b32b8144
FG
119 geometry1, geometry2, is_origin);
120
121 }
122 }
123 }
124
125 BOOST_CHECK_MESSAGE(has_origin,
126 " caseid=" << case_id
127 << " origin not found");
128
129 if (!has_origin)
130 {
131 for (std::size_t turn_index = 0; turn_index < turns.size(); turn_index++)
132 {
133 turn_info const& turn = turns[turn_index];
134 if (bg::equals(turn.point, turn_point))
135 {
136 for (int i = 0; i < 2; i++)
137 {
138 Point point1, point2, point3;
139 bg::copy_segment_points<false, false>(geometry1, geometry2,
140 turn.operations[i].seg_id, point1, point2, point3);
141// std::cout << "Turn " << turn_index << " op " << i << " point1=" << bg::wkt(point1) << std::endl;
142 }
143 }
144 }
145 return result;
146 }
147
148
149 sbs.apply(turn_point);
150
151 sbs.find_open();
152 sbs.assign_zones(detail::overlay::operation_union);
153
154 std::size_t const open_count = sbs.open_count(detail::overlay::operation_union);
155 std::size_t const max_rank = sbs.m_ranked_points.back().rank;
11fdf7f2 156 std::vector<bg::signed_size_type> right_count(max_rank + 1, -1);
b32b8144
FG
157
158 int previous_rank = -1;
159 int previous_to_rank = -1;
160 for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
161 {
162 typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];
163
164 int const rank = static_cast<int>(ranked_point.rank);
165 bool const set_right = rank != previous_to_rank;
166 if (rank != previous_rank)
167 {
168 BOOST_CHECK_MESSAGE(rank == previous_rank + 1,
169 " caseid=" << case_id
170 << " ranks: conflict in ranks=" << ranked_point.rank
171 << " vs " << previous_rank + 1);
172 previous_rank = rank;
173 }
174
175 if (ranked_point.direction != bg::detail::overlay::sort_by_side::dir_to)
176 {
177 continue;
178 }
179
180 previous_to_rank = rank;
181 if (set_right)
182 {
183 right_count[rank] = ranked_point.count_right;
184 }
185 else
186 {
187 BOOST_CHECK_MESSAGE(right_count[rank] == int(ranked_point.count_right),
188 " caseid=" << case_id
189 << " ranks: conflict in right_count=" << ranked_point.count_right
190 << " vs " << right_count[rank]);
191 }
192
193 }
194 BOOST_CHECK_MESSAGE(open_count == expected_open_count,
195 " caseid=" << case_id
196 << " open_count: expected=" << expected_open_count
197 << " detected=" << open_count);
198
199 BOOST_CHECK_MESSAGE(max_rank == expected_max_rank,
200 " caseid=" << case_id
201 << " max_rank: expected=" << expected_max_rank
202 << " detected=" << max_rank);
203
204 BOOST_CHECK_MESSAGE(right_count == expected_right_count,
205 " caseid=" << case_id
206 << " right count: expected=" << as_string(expected_right_count)
207 << " detected=" << as_string(right_count));
208
209#if defined(TEST_WITH_SVG)
210 debug::sorted_side_map(case_id, sbs, turn_point, geometry1, geometry2);
211#endif
212
213 return result;
214}
215
216
217template <typename T>
218void test_basic(std::string const& case_id,
219 std::string const& wkt1,
220 std::string const& wkt2,
221 std::string const& wkt_turn_point,
222 std::string const& wkt_origin_point,
223 std::size_t expected_open_count,
224 std::size_t expected_max_rank,
11fdf7f2 225 std::vector<bg::signed_size_type> const& expected_right_count)
b32b8144
FG
226{
227 typedef bg::model::point<T, 2, bg::cs::cartesian> point_type;
228 typedef bg::model::polygon<point_type> polygon;
229 typedef bg::model::multi_polygon<polygon> multi_polygon;
230
231 multi_polygon g1;
232 bg::read_wkt(wkt1, g1);
233
234 multi_polygon g2;
235 bg::read_wkt(wkt2, g2);
236
237 point_type turn_point, origin_point;
238 bg::read_wkt(wkt_turn_point, turn_point);
239 bg::read_wkt(wkt_origin_point, origin_point);
240
241 // Reverse if necessary
242 bg::correct(g1);
243 bg::correct(g2);
244
245 typedef typename bg::rescale_overlay_policy_type
246 <
247 multi_polygon,
248 multi_polygon
249 >::type rescale_policy_type;
250
251 rescale_policy_type robust_policy
252 = bg::get_rescale_policy<rescale_policy_type>(g1, g2);
253
1e59de90 254 typedef typename bg::strategies::relate::services::default_strategy
b32b8144 255 <
1e59de90 256 multi_polygon, multi_polygon
b32b8144
FG
257 >::type strategy_type;
258
259 strategy_type strategy;
260
261 apply_get_turns(case_id, g1, g2, turn_point, origin_point,
262 robust_policy, strategy,
263 expected_open_count, expected_max_rank, expected_right_count);
264}
265
b32b8144
FG
266template <typename T>
267void test_all()
268{
269 test_basic<T>("simplex",
270 "MULTIPOLYGON(((0 2,1 2,1 1,0 1,0 2)))",
271 "MULTIPOLYGON(((1 0,1 1,2 1,2 0,1, 0)))",
272 "POINT(1 1)", "POINT(1 0)",
1e59de90 273 2, 3, {-1, 1, -1, 1});
b32b8144
FG
274
275 test_basic<T>("dup1",
276 "MULTIPOLYGON(((0 2,1 2,1 1,0 1,0 2)))",
277 "MULTIPOLYGON(((1 0,1 1,2 1,2 0,1, 0)),((0 2,1 2,1 1,0 1,0 2)))",
278 "POINT(1 1)", "POINT(1 0)",
1e59de90 279 2, 3, {-1, 1, -1, 2});
b32b8144
FG
280
281 test_basic<T>("dup2",
282 "MULTIPOLYGON(((0 2,1 2,1 1,0 1,0 2)),((1 0,1 1,2 1,2 0,1, 0)))",
283 "MULTIPOLYGON(((1 0,1 1,2 1,2 0,1, 0)))",
284 "POINT(1 1)", "POINT(1 0)",
1e59de90 285 2, 3, {-1, 2, -1, 1});
b32b8144
FG
286
287 test_basic<T>("dup3",
288 "MULTIPOLYGON(((0 2,1 2,1 1,0 1,0 2)),((1 0,1 1,2 1,2 0,1, 0)))",
289 "MULTIPOLYGON(((1 0,1 1,2 1,2 0,1, 0)),((0 2,1 2,1 1,0 1,0 2)))",
290 "POINT(1 1)", "POINT(1 0)",
1e59de90 291 2, 3, {-1, 2, -1, 2});
b32b8144
FG
292
293 test_basic<T>("threequart1",
294 "MULTIPOLYGON(((0 2,1 2,1 1,0 1,0 2)),((1 0,1 1,2 1,2 0,1, 0)))",
295 "MULTIPOLYGON(((1 2,2 2,2 1,1 1,1 2)))",
296 "POINT(1 1)", "POINT(1 0)",
1e59de90 297 1, 3, {-1, 1, 1, 1});
b32b8144
FG
298
299 test_basic<T>("threequart2",
300 "MULTIPOLYGON(((0 2,1 2,1 1,0 1,0 2)),((1 0,1 1,2 1,2 0,1, 0)))",
301 "MULTIPOLYGON(((1 2,2 2,2 1,1 1,1 2)),((2 0,1 0,1 1,2 0)))",
302 "POINT(1 1)", "POINT(1 0)",
1e59de90 303 1, 4, {-1, 2, 1, 1, 1});
b32b8144
FG
304
305 test_basic<T>("threequart3",
306 "MULTIPOLYGON(((0 2,1 2,1 1,0 1,0 2)),((1 0,1 1,2 1,2 0,1, 0)))",
307 "MULTIPOLYGON(((1 2,2 2,2 1,1 1,1 2)),((2 0,1 0,1 1,2 0)),((0 1,0 2,1 1,0 1)))",
308 "POINT(1 1)", "POINT(1 0)",
1e59de90 309 1, 5, {-1, 2, 1, 1, -1, 2});
b32b8144
FG
310
311 test_basic<T>("full1",
312 "MULTIPOLYGON(((0 2,1 2,1 1,0 1,0 2)),((1 0,1 1,2 1,2 0,1, 0)))",
313 "MULTIPOLYGON(((1 2,2 2,2 1,1 1,1 2)),((0 0,0 1,1 1,1 0,0 0)))",
314 "POINT(1 1)", "POINT(1 0)",
1e59de90 315 0, 3, {1, 1, 1, 1});
b32b8144
FG
316
317 test_basic<T>("hole1",
318 "MULTIPOLYGON(((0 0,0 3,2 3,2 2,3 2,3 0,0 0),(1 1,2 1,2 2,1 2,1 1)),((4 2,3 2,3 3,4 3,4 2)))",
319 "MULTIPOLYGON(((1 0,1 1,2 1,2 2,1 2,1 4,4 4,4 0,1, 0),(3 2,3 3,2 3,2 2,3 2)))",
320 "POINT(1 2)", "POINT(2 2)",
1e59de90 321 1, 2, {-1, 2, 1});
b32b8144
FG
322
323 test_basic<T>("hole2",
324 "MULTIPOLYGON(((0 0,0 3,2 3,2 2,3 2,3 0,0 0),(1 1,2 1,2 2,1 2,1 1)),((4 2,3 2,3 3,4 3,4 2)))",
325 "MULTIPOLYGON(((1 0,1 1,2 1,2 2,1 2,1 4,4 4,4 0,1, 0),(3 2,3 3,2 3,2 2,3 2)))",
326 "POINT(2 2)", "POINT(2 1)",
1e59de90 327 2, 3, {-1, 2, -1, 2});
b32b8144
FG
328
329 test_basic<T>("hole3",
330 "MULTIPOLYGON(((0 0,0 3,2 3,2 2,3 2,3 0,0 0),(1 1,2 1,2 2,1 2,1 1)),((4 2,3 2,3 3,4 3,4 2)))",
331 "MULTIPOLYGON(((1 0,1 1,2 1,2 2,1 2,1 4,4 4,4 0,1, 0),(3 2,3 3,2 3,2 2,3 2)))",
332 "POINT(3 2)", "POINT(2 2)",
1e59de90 333 1, 3, {-1, 2, -1, 2});
b32b8144
FG
334}
335
336
337int test_main(int, char* [])
338{
339 test_all<double>();
340 return 0;
341}