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