]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
20effc67 | 2 | // Robustness Test |
7c673cae | 3 | |
1e59de90 | 4 | // Copyright (c) 2009-2021 Barend Gehrels, Amsterdam, the Netherlands. |
7c673cae FG |
5 | |
6 | // Use, modification and distribution is subject to the Boost Software License, | |
7 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
8 | // http://www.boost.org/LICENSE_1_0.txt) | |
9 | ||
7c673cae FG |
10 | #define BOOST_GEOMETRY_NO_BOOST_TEST |
11 | ||
1e59de90 TL |
12 | #ifndef BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE |
13 | #define BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE | |
14 | #endif | |
15 | ||
7c673cae FG |
16 | #include <test_overlay_p_q.hpp> |
17 | ||
18 | #include <boost/program_options.hpp> | |
7c673cae FG |
19 | #include <boost/random/linear_congruential.hpp> |
20 | #include <boost/random/uniform_int.hpp> | |
21 | #include <boost/random/uniform_real.hpp> | |
22 | #include <boost/random/variate_generator.hpp> | |
23 | ||
24 | ||
25 | struct star_params | |
26 | { | |
27 | int count; // points of ellipse, not of star | |
28 | double factor_1; | |
29 | double factor_2; | |
30 | double center_x; | |
31 | double center_y; | |
32 | double rotation; | |
33 | star_params(int c, double f1, double f2, double x, double y, double r = 0) | |
34 | : count(c) | |
35 | , factor_1(f1) | |
36 | , factor_2(f2) | |
37 | , center_x(x) | |
38 | , center_y(y) | |
39 | , rotation(r) | |
40 | {} | |
41 | }; | |
42 | ||
43 | ||
44 | ||
45 | template <typename Polygon> | |
46 | inline void make_star(Polygon& polygon, star_params const& p) | |
47 | { | |
48 | typedef typename bg::point_type<Polygon>::type P; | |
49 | typedef typename bg::select_most_precise | |
50 | < | |
51 | typename bg::coordinate_type<Polygon>::type, | |
52 | long double | |
53 | >::type coordinate_type; | |
54 | ||
55 | // Create star | |
56 | coordinate_type cx = 25.0; | |
57 | coordinate_type cy = 25.0; | |
58 | ||
59 | coordinate_type dx = 50.0; | |
60 | coordinate_type dy = 50.0; | |
61 | ||
62 | coordinate_type half = 0.5; | |
63 | coordinate_type two = 2.0; | |
64 | ||
65 | coordinate_type a1 = coordinate_type(p.factor_1) * half * dx; | |
66 | coordinate_type b1 = coordinate_type(p.factor_1) * half * dy; | |
67 | coordinate_type a2 = coordinate_type(p.factor_2) * half * dx; | |
68 | coordinate_type b2 = coordinate_type(p.factor_2) * half * dy; | |
69 | ||
70 | coordinate_type pi = boost::math::constants::pi<long double>(); | |
71 | coordinate_type delta = pi * two / coordinate_type(p.count - 1); | |
72 | coordinate_type angle = coordinate_type(p.rotation) * delta; | |
73 | for (int i = 0; i < p.count - 1; i++, angle += delta) | |
74 | { | |
75 | bool even = i % 2 == 0; | |
76 | coordinate_type s = sin(angle); | |
77 | coordinate_type c = cos(angle); | |
78 | coordinate_type x = p.center_x + cx + (even ? a1 : a2) * s; | |
79 | coordinate_type y = p.center_y + cy + (even ? b1 : b2) * c; | |
80 | bg::exterior_ring(polygon).push_back(bg::make<P>(x, y)); | |
81 | ||
82 | } | |
83 | bg::exterior_ring(polygon).push_back(bg::exterior_ring(polygon).front()); | |
84 | bg::correct(polygon); | |
85 | } | |
86 | ||
87 | ||
88 | template <typename T, bool Clockwise, bool Closed> | |
89 | void test_star_ellipse(int seed, int index, star_params const& par_p, | |
90 | star_params const& par_q, p_q_settings const& settings) | |
91 | { | |
92 | typedef bg::model::d2::point_xy<T> point_type; | |
93 | typedef bg::model::polygon<point_type, Clockwise, Closed> polygon; | |
94 | ||
95 | polygon p, q; | |
96 | make_star(p, par_p); | |
97 | make_star(q, par_q); | |
98 | ||
99 | std::ostringstream out; | |
20effc67 | 100 | out << "star_ellipse_" << seed << "_" << index; |
7c673cae FG |
101 | test_overlay_p_q<polygon, T>(out.str(), p, q, settings); |
102 | } | |
103 | ||
104 | template <typename T, bool Clockwise, bool Closed> | |
105 | void test_type(int seed, int count, p_q_settings const& settings) | |
106 | { | |
20effc67 | 107 | auto const t0 = std::chrono::high_resolution_clock::now(); |
7c673cae FG |
108 | typedef boost::minstd_rand base_generator_type; |
109 | ||
110 | //boost::uniform_real<> random_factor(0.5, 1.2); | |
111 | //boost::uniform_real<> random_location(-10.0, 10.0); | |
112 | //boost::uniform_int<> random_points(5, 20); | |
113 | ||
114 | // This set (next 4 lines) are now solved for the most part | |
115 | // 2009-12-03, 3 or 4 errors in 1000000 calls | |
116 | // 2009-12-07, no errors in 1000000 calls | |
117 | //boost::uniform_real<> random_factor(1.0 - 1e-3, 1.0 + 1e-3); | |
118 | //boost::uniform_real<> random_location(-1e-3, 1e-3); | |
119 | //boost::uniform_real<> random_rotation(-1e-3, 1e-3); | |
120 | //boost::uniform_int<> random_points(3, 3); | |
121 | ||
122 | // 2009-12-08, still errors, see notes | |
123 | // 2009-12-09, (probably) solved by order on side | |
124 | // 2010-01-16: solved (no errors in 1000000 calls) | |
125 | //boost::uniform_real<> random_factor(1.0 - 1e-3, 1.0 + 1e-3); | |
126 | //boost::uniform_real<> random_location(-1e-3, -1e-3); | |
127 | //boost::uniform_real<> random_rotation(-1e-3, 1e-3); | |
128 | //boost::uniform_int<> random_points(3, 4); | |
129 | ||
130 | // This set (next 4 lines) are now solved ("distance-zero"/"merge iiii" problem) | |
131 | // 2009-12-03: 5,50 -> 2:1 000 000 wrong (2009-12-03) | |
132 | // 2010-01-16: solved (no errors in 10000000 calls) | |
133 | boost::uniform_real<> random_factor(0.3, 1.2); | |
134 | boost::uniform_real<> random_location(-20.0, +20.0); // -25.0, +25.0 | |
135 | boost::uniform_real<> random_rotation(0, 0.5); | |
136 | boost::uniform_int<> random_points(5, 15); | |
137 | ||
138 | base_generator_type generator(seed); | |
139 | ||
140 | boost::variate_generator<base_generator_type&, boost::uniform_real<> > | |
141 | factor_generator(generator, random_factor); | |
142 | ||
143 | boost::variate_generator<base_generator_type&, boost::uniform_real<> > | |
144 | location_generator(generator, random_location); | |
145 | ||
146 | boost::variate_generator<base_generator_type&, boost::uniform_real<> > | |
147 | rotation_generator(generator, random_rotation); | |
148 | ||
149 | boost::variate_generator<base_generator_type&, boost::uniform_int<> > | |
150 | int_generator(generator, random_points); | |
151 | ||
152 | for(int i = 0; i < count; i++) | |
153 | { | |
154 | test_star_ellipse<T, Clockwise, Closed>(seed, i + 1, | |
155 | star_params(int_generator() * 2 + 1, | |
156 | factor_generator(), factor_generator(), | |
157 | location_generator(), location_generator(), rotation_generator()), | |
158 | star_params(int_generator() * 2 + 1, | |
159 | factor_generator(), factor_generator(), | |
160 | location_generator(), location_generator(), rotation_generator()), | |
161 | settings); | |
162 | } | |
20effc67 TL |
163 | auto const t = std::chrono::high_resolution_clock::now(); |
164 | auto const elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t - t0).count(); | |
7c673cae FG |
165 | std::cout |
166 | << "type: " << string_from_type<T>::name() | |
20effc67 | 167 | << " time: " << elapsed_ms / 1000.0 << std::endl; |
7c673cae FG |
168 | } |
169 | ||
170 | template <bool Clockwise, bool Closed> | |
171 | void test_all(std::string const& type, int seed, int count, p_q_settings settings) | |
172 | { | |
1e59de90 | 173 | #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) |
7c673cae FG |
174 | if (type == "float") |
175 | { | |
176 | test_type<float, Clockwise, Closed>(seed, count, settings); | |
177 | } | |
178 | else if (type == "double") | |
1e59de90 | 179 | #endif |
7c673cae FG |
180 | { |
181 | test_type<double, Clockwise, Closed>(seed, count, settings); | |
182 | } | |
7c673cae FG |
183 | } |
184 | ||
185 | ||
186 | int main(int argc, char** argv) | |
187 | { | |
20effc67 | 188 | BoostGeometryWriteTestConfiguration(); |
7c673cae FG |
189 | try |
190 | { | |
191 | namespace po = boost::program_options; | |
192 | po::options_description description("=== random_ellipses_stars ===\nAllowed options"); | |
193 | ||
194 | int count = 1; | |
195 | int seed = static_cast<unsigned int>(std::time(0)); | |
1e59de90 | 196 | std::string type = "double"; |
7c673cae FG |
197 | bool ccw = false; |
198 | bool open = false; | |
199 | p_q_settings settings; | |
200 | ||
201 | description.add_options() | |
202 | ("help", "Help message") | |
203 | ("seed", po::value<int>(&seed), "Initialization seed for random generator") | |
204 | ("count", po::value<int>(&count)->default_value(1), "Number of tests") | |
205 | ("diff", po::value<bool>(&settings.also_difference)->default_value(false), "Include testing on difference") | |
1e59de90 | 206 | #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) |
7c673cae FG |
207 | ("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons") |
208 | ("open", po::value<bool>(&open)->default_value(false), "Open polygons") | |
1e59de90 TL |
209 | ("type", po::value<std::string>(&type)->default_value("double"), "Type (float,double)") |
210 | #endif | |
7c673cae FG |
211 | ("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests") |
212 | ("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests") | |
213 | ; | |
214 | ||
215 | po::variables_map varmap; | |
216 | po::store(po::parse_command_line(argc, argv, description), varmap); | |
217 | po::notify(varmap); | |
218 | ||
219 | if (varmap.count("help")) | |
220 | { | |
221 | std::cout << description << std::endl; | |
222 | return 1; | |
223 | } | |
224 | ||
1e59de90 | 225 | #if ! defined(BOOST_GEOMETRY_TEST_ONLY_ONE_TYPE) |
7c673cae FG |
226 | if (ccw && open) |
227 | { | |
228 | test_all<false, false>(type, seed, count, settings); | |
229 | } | |
230 | else if (ccw) | |
231 | { | |
232 | test_all<false, true>(type, seed, count, settings); | |
233 | } | |
234 | else if (open) | |
235 | { | |
236 | test_all<true, false>(type, seed, count, settings); | |
237 | } | |
238 | else | |
1e59de90 | 239 | #endif |
7c673cae FG |
240 | { |
241 | test_all<true, true>(type, seed, count, settings); | |
242 | } | |
243 | } | |
244 | catch(std::exception const& e) | |
245 | { | |
246 | std::cout << "Exception " << e.what() << std::endl; | |
247 | } | |
248 | catch(...) | |
249 | { | |
250 | std::cout << "Other exception" << std::endl; | |
251 | } | |
252 | ||
253 | return 0; | |
254 | } |