• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Robustness 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 #include <test_overlay_p_q.hpp>
13 
14 #include <boost/program_options.hpp>
15 #include <boost/random/linear_congruential.hpp>
16 #include <boost/random/uniform_int.hpp>
17 #include <boost/random/uniform_real.hpp>
18 #include <boost/random/variate_generator.hpp>
19 #include <boost/timer.hpp>
20 
21 
22 template <typename Polygon, typename Generator>
make_polygon(Polygon & polygon,Generator & generator,bool triangular)23 inline void make_polygon(Polygon& polygon, Generator& generator, bool triangular)
24 {
25     typedef typename bg::point_type<Polygon>::type point_type;
26     typedef typename bg::coordinate_type<Polygon>::type coordinate_type;
27 
28     coordinate_type x, y;
29     x = generator();
30     y = generator();
31 
32     typename bg::ring_type<Polygon>::type& ring = bg::exterior_ring(polygon);
33 
34     point_type p;
35     bg::set<0>(p, x); bg::set<1>(p, y); ring.push_back(p);
36     bg::set<0>(p, x); bg::set<1>(p, y + 1); ring.push_back(p);
37     bg::set<0>(p, x + 1); bg::set<1>(p, y + 1); ring.push_back(p);
38     bg::set<0>(p, x + 1); bg::set<1>(p, y); ring.push_back(p);
39     bg::set<0>(p, x); bg::set<1>(p, y); ring.push_back(p);
40 
41     if (triangular)
42     {
43         // Remove a point depending on generator
44         int c = generator() % 4;
45         if (c >= 1 && c <= 3)
46         {
47             ring.erase(ring.begin() + c);
48         }
49     }
50 }
51 
52 
53 
54 template <typename MultiPolygon, typename Generator>
test_recursive_boxes(MultiPolygon & result,int & index,Generator & generator,int level,bool triangular,p_q_settings const & settings)55 bool test_recursive_boxes(MultiPolygon& result, int& index,
56             Generator& generator,
57             int level, bool triangular, p_q_settings const& settings)
58 {
59     MultiPolygon p, q;
60 
61     // Generate two boxes
62     if (level == 0)
63     {
64         p.resize(1);
65         q.resize(1);
66         make_polygon(p.front(), generator, triangular);
67         make_polygon(q.front(), generator, triangular);
68         bg::correct(p);
69         bg::correct(q);
70     }
71     else
72     {
73         bg::correct(p);
74         bg::correct(q);
75         if (! test_recursive_boxes(p, index, generator, level - 1, triangular, settings)
76             || ! test_recursive_boxes(q, index, generator, level - 1, triangular, settings))
77         {
78             return false;
79         }
80     }
81 
82     typedef typename boost::range_value<MultiPolygon>::type polygon;
83 
84     std::ostringstream out;
85     out << "recursive_box_" << index++ << "_" << level;
86 
87     if (! test_overlay_p_q
88         <
89             polygon,
90             typename bg::coordinate_type<MultiPolygon>::type
91         >(out.str(), p, q, settings))
92     {
93         return false;
94     }
95 
96     MultiPolygon mp;
97     bg::detail::union_::union_insert
98         <
99             polygon
100         >(p, q, std::back_inserter(mp));
101 
102     bg::unique(mp);
103     bg::simplify(mp, result, 0.01);
104     bg::correct(mp);
105     return true;
106 }
107 
108 
109 template <typename T, bool Clockwise, bool Closed>
test_all(int seed,int count,int field_size,int level,bool triangular,p_q_settings const & settings)110 void test_all(int seed, int count, int field_size, int level, bool triangular, p_q_settings const& settings)
111 {
112     boost::timer t;
113 
114     typedef boost::minstd_rand base_generator_type;
115 
116     base_generator_type generator(seed);
117 
118     boost::uniform_int<> random_coordinate(0, field_size - 1);
119     boost::variate_generator<base_generator_type&, boost::uniform_int<> >
120         coordinate_generator(generator, random_coordinate);
121 
122     typedef bg::model::polygon
123         <
124             bg::model::d2::point_xy<T>, Clockwise, Closed
125         > polygon;
126     typedef bg::model::multi_polygon<polygon> mp;
127 
128 
129     int index = 0;
130     for(int i = 0; i < count; i++)
131     {
132         mp p;
133         test_recursive_boxes<mp>(p, index, coordinate_generator, level, triangular, settings);
134     }
135     std::cout
136         << "polygons: " << index
137         << " type: " << string_from_type<T>::name()
138         << " time: " << t.elapsed()  << std::endl;
139 }
140 
main(int argc,char ** argv)141 int main(int argc, char** argv)
142 {
143     BoostGeometryWriteTestConfiguration();
144     try
145     {
146         namespace po = boost::program_options;
147         po::options_description description("=== recursive_polygons ===\nAllowed options");
148 
149         int count = 1;
150         int seed = static_cast<unsigned int>(std::time(0));
151         int level = 3;
152         int field_size = 10;
153         bool ccw = false;
154         bool open = false;
155         p_q_settings settings;
156         std::string form = "box";
157 
158         description.add_options()
159             ("help", "Help message")
160             ("seed", po::value<int>(&seed), "Initialization seed for random generator")
161             ("count", po::value<int>(&count)->default_value(1), "Number of tests")
162             ("diff", po::value<bool>(&settings.also_difference)->default_value(false), "Include testing on difference")
163             ("validity", po::value<bool>(&settings.validity)->default_value(true), "Include testing on validity")
164             ("level", po::value<int>(&level)->default_value(3), "Level to reach (higher->slower)")
165             ("size", po::value<int>(&field_size)->default_value(10), "Size of the field")
166             ("form", po::value<std::string>(&form)->default_value("box"), "Form of the polygons (box, triangle)")
167             ("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
168             ("open", po::value<bool>(&open)->default_value(false), "Open polygons")
169             ("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
170             ("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
171         ;
172 
173         po::variables_map varmap;
174         po::store(po::parse_command_line(argc, argv, description), varmap);
175         po::notify(varmap);
176 
177         if (varmap.count("help")
178             || (form != "box" && form != "triangle"))
179         {
180             std::cout << description << std::endl;
181             return 1;
182         }
183 
184         bool triangular = form != "box";
185 
186 
187         if (ccw && open)
188         {
189             test_all<double, false, false>(seed, count, field_size, level, triangular, settings);
190         }
191         else if (ccw)
192         {
193             test_all<double, false, true>(seed, count, field_size, level, triangular, settings);
194         }
195         else if (open)
196         {
197             test_all<double, true, false>(seed, count, field_size, level, triangular, settings);
198         }
199         else
200         {
201             test_all<double, true, true>(seed, count, field_size, level, triangular, settings);
202         }
203 
204 #if defined(HAVE_TTMATH)
205         // test_all<ttmath_big, true, true>(seed, count, max, svg, level);
206 #endif
207     }
208     catch(std::exception const& e)
209     {
210         std::cout << "Exception " << e.what() << std::endl;
211     }
212     catch(...)
213     {
214         std::cout << "Other exception" << std::endl;
215     }
216 
217     return 0;
218 }
219