#### /Src/Dependencies/Boost/libs/geometry/test/algorithms/overlay/robustness/random_ellipses_stars.cpp

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