]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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_REPORT_OVERLAY_ERROR | |
11 | #define BOOST_GEOMETRY_NO_BOOST_TEST | |
12 | ||
13 | #include <test_overlay_p_q.hpp> | |
14 | ||
15 | #include <boost/program_options.hpp> | |
16 | #include <boost/random/linear_congruential.hpp> | |
17 | #include <boost/random/uniform_int.hpp> | |
18 | #include <boost/random/uniform_real.hpp> | |
19 | #include <boost/random/variate_generator.hpp> | |
20 | #include <boost/timer.hpp> | |
21 | ||
22 | ||
23 | template <typename Polygon, typename Generator> | |
24 | inline void make_polygon(Polygon& polygon, Generator& generator, bool triangular) | |
25 | { | |
26 | typedef typename bg::point_type<Polygon>::type point_type; | |
27 | typedef typename bg::coordinate_type<Polygon>::type coordinate_type; | |
28 | ||
29 | coordinate_type x, y; | |
30 | x = generator(); | |
31 | y = generator(); | |
32 | ||
33 | typename bg::ring_type<Polygon>::type& ring = bg::exterior_ring(polygon); | |
34 | ||
35 | point_type p; | |
36 | bg::set<0>(p, x); bg::set<1>(p, y); ring.push_back(p); | |
37 | bg::set<0>(p, x); bg::set<1>(p, y + 1); ring.push_back(p); | |
38 | bg::set<0>(p, x + 1); bg::set<1>(p, y + 1); ring.push_back(p); | |
39 | bg::set<0>(p, x + 1); bg::set<1>(p, y); ring.push_back(p); | |
40 | bg::set<0>(p, x); bg::set<1>(p, y); ring.push_back(p); | |
41 | ||
42 | if (triangular) | |
43 | { | |
44 | // Remove a point depending on generator | |
45 | int c = generator() % 4; | |
46 | if (c >= 1 && c <= 3) | |
47 | { | |
48 | ring.erase(ring.begin() + c); | |
49 | } | |
50 | } | |
51 | } | |
52 | ||
53 | ||
54 | ||
55 | template <typename MultiPolygon, typename Generator> | |
56 | bool test_recursive_boxes(MultiPolygon& result, int& index, | |
57 | Generator& generator, | |
58 | int level, bool triangular, p_q_settings const& settings) | |
59 | { | |
60 | MultiPolygon p, q; | |
61 | ||
62 | // Generate two boxes | |
63 | if (level == 0) | |
64 | { | |
65 | p.resize(1); | |
66 | q.resize(1); | |
67 | make_polygon(p.front(), generator, triangular); | |
68 | make_polygon(q.front(), generator, triangular); | |
69 | bg::correct(p); | |
70 | bg::correct(q); | |
71 | } | |
72 | else | |
73 | { | |
74 | bg::correct(p); | |
75 | bg::correct(q); | |
76 | if (! test_recursive_boxes(p, index, generator, level - 1, triangular, settings) | |
77 | || ! test_recursive_boxes(q, index, generator, level - 1, triangular, settings)) | |
78 | { | |
79 | return false; | |
80 | } | |
81 | } | |
82 | ||
83 | typedef typename boost::range_value<MultiPolygon>::type polygon; | |
84 | ||
85 | std::ostringstream out; | |
86 | out << "recursive_box_" << index++ << "_" << level; | |
87 | ||
88 | if (! test_overlay_p_q | |
89 | < | |
90 | polygon, | |
91 | typename bg::coordinate_type<MultiPolygon>::type | |
92 | >(out.str(), p, q, settings)) | |
93 | { | |
94 | return false; | |
95 | } | |
96 | ||
97 | MultiPolygon mp; | |
98 | bg::detail::union_::union_insert | |
99 | < | |
100 | polygon | |
101 | >(p, q, std::back_inserter(mp)); | |
102 | ||
103 | bg::unique(mp); | |
104 | bg::simplify(mp, result, 0.01); | |
105 | bg::correct(mp); | |
106 | return true; | |
107 | } | |
108 | ||
109 | ||
110 | template <typename T, bool Clockwise, bool Closed> | |
111 | void test_all(int seed, int count, int field_size, int level, bool triangular, p_q_settings const& settings) | |
112 | { | |
113 | boost::timer t; | |
114 | ||
115 | typedef boost::minstd_rand base_generator_type; | |
116 | ||
117 | base_generator_type generator(seed); | |
118 | ||
119 | boost::uniform_int<> random_coordinate(0, field_size - 1); | |
120 | boost::variate_generator<base_generator_type&, boost::uniform_int<> > | |
121 | coordinate_generator(generator, random_coordinate); | |
122 | ||
123 | typedef bg::model::polygon | |
124 | < | |
125 | bg::model::d2::point_xy<T>, Clockwise, Closed | |
126 | > polygon; | |
127 | typedef bg::model::multi_polygon<polygon> mp; | |
128 | ||
129 | ||
130 | int index = 0; | |
131 | for(int i = 0; i < count; i++) | |
132 | { | |
133 | mp p; | |
134 | test_recursive_boxes<mp>(p, index, coordinate_generator, level, triangular, settings); | |
135 | } | |
136 | std::cout | |
137 | << "polygons: " << index | |
138 | << " type: " << string_from_type<T>::name() | |
139 | << " time: " << t.elapsed() << std::endl; | |
140 | } | |
141 | ||
142 | int main(int argc, char** argv) | |
143 | { | |
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") | |
b32b8144 | 163 | ("validity", po::value<bool>(&settings.validity)->default_value(true), "Include testing on validity") |
7c673cae FG |
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 | } |