1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // Use, modification and distribution is subject to the Boost Software License,
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8
9 #ifndef BOOST_GEOMETRY_TEST_SIMPLIFY_HPP
10 #define BOOST_GEOMETRY_TEST_SIMPLIFY_HPP
11
12 // Test-functionality, shared between single and multi tests
13
14 #include <iomanip>
15 #include <sstream>
16 #include <geometry_test_common.hpp>
17 #include <boost/geometry/algorithms/correct_closure.hpp>
18 #include <boost/geometry/algorithms/equals.hpp>
19 #include <boost/geometry/algorithms/simplify.hpp>
20 #include <boost/geometry/algorithms/distance.hpp>
21 #include <boost/geometry/strategies/strategies.hpp>
22 #include <boost/geometry/io/wkt/wkt.hpp>
23 #include <boost/variant/variant.hpp>
24
25
26 template
27 <
28 typename GeometryForTag,
29 typename Tag = typename bg::tag<GeometryForTag>::type
30 >
31 struct test_equality
32 {
33 template <typename Geometry, typename Expected>
applytest_equality34 static void apply(Geometry const& geometry, Expected const& expected)
35 {
36 // Verify both spatially equal AND number of points, because several
37 // of the tests only check explicitly on collinear points being
38 // simplified away
39 bool const result
40 = bg::equals(geometry, expected)
41 && bg::num_points(geometry) == bg::num_points(expected);
42
43 BOOST_CHECK_MESSAGE(result,
44 " result: " << bg::wkt(geometry) << " " << bg::area(geometry)
45 << " expected: " << bg::wkt(expected) << " " << bg::area(expected));
46
47 }
48 };
49
50 // Linestring does NOT yet have "geometry::equals" implemented
51 // Until then, WKT's are compared (which is acceptable for linestrings, but not
52 // for polygons, because simplify might rotate them)
53 template <typename GeometryForTag>
54 struct test_equality<GeometryForTag, bg::linestring_tag>
55 {
56 template <typename Geometry, typename Expected>
applytest_equality57 static void apply(Geometry const& geometry, Expected const& expected)
58 {
59 std::ostringstream out1, out2;
60 out1 << bg::wkt(geometry);
61 out2 << bg::wkt(expected);
62 BOOST_CHECK_EQUAL(out1.str(), out2.str());
63 }
64 };
65
66
67 template <typename Tag>
68 struct test_inserter
69 {
70 template <typename Geometry, typename Expected>
applytest_inserter71 static void apply(Geometry& , Expected const& , double )
72 {}
73 };
74
75 template <>
76 struct test_inserter<bg::linestring_tag>
77 {
78 template <typename Geometry, typename Expected, typename DistanceMeasure>
applytest_inserter79 static void apply(Geometry& geometry,
80 Expected const& expected,
81 DistanceMeasure const& distance)
82 {
83 {
84 Geometry simplified;
85 bg::detail::simplify::simplify_insert(geometry,
86 std::back_inserter(simplified), distance);
87
88 test_equality<Geometry>::apply(simplified, expected);
89 }
90
91 #ifdef TEST_PULL89
92 {
93 typedef typename bg::point_type<Geometry>::type point_type;
94 typedef typename bg::strategy::distance::detail::projected_point_ax<>::template result_type<point_type, point_type>::type distance_type;
95 typedef bg::strategy::distance::detail::projected_point_ax_less<distance_type> less_comparator;
96
97 distance_type max_distance(distance);
98 less_comparator less(max_distance);
99
100 bg::strategy::simplify::detail::douglas_peucker
101 <
102 point_type,
103 bg::strategy::distance::detail::projected_point_ax<>,
104 less_comparator
105 > strategy(less);
106
107 Geometry simplified;
108 bg::detail::simplify::simplify_insert(geometry,
109 std::back_inserter(simplified), max_distance, strategy);
110
111 test_equality<Geometry>::apply(simplified, expected);
112 }
113 #endif
114 }
115 };
116
117 template <typename Geometry, typename Expected, typename DistanceMeasure>
check_geometry(Geometry const & geometry,Expected const & expected,DistanceMeasure const & distance)118 void check_geometry(Geometry const& geometry,
119 Expected const& expected,
120 DistanceMeasure const& distance)
121 {
122 Geometry simplified;
123 bg::simplify(geometry, simplified, distance);
124 test_equality<Expected>::apply(simplified, expected);
125 }
126
127 template <typename Geometry, typename Expected, typename Strategy, typename DistanceMeasure>
check_geometry(Geometry const & geometry,Expected const & expected,DistanceMeasure const & distance,Strategy const & strategy)128 void check_geometry(Geometry const& geometry,
129 Expected const& expected,
130 DistanceMeasure const& distance,
131 Strategy const& strategy)
132 {
133 Geometry simplified;
134 bg::simplify(geometry, simplified, distance, strategy);
135 test_equality<Expected>::apply(simplified, expected);
136 }
137
138 template <typename Geometry, typename DistanceMeasure>
check_geometry_with_area(Geometry const & geometry,double expected_area,DistanceMeasure const & distance)139 void check_geometry_with_area(Geometry const& geometry,
140 double expected_area,
141 DistanceMeasure const& distance)
142 {
143 Geometry simplified;
144 bg::simplify(geometry, simplified, distance);
145 BOOST_CHECK_CLOSE(bg::area(simplified), expected_area, 0.01);
146 }
147
148
149 template <typename Geometry, typename DistanceMeasure>
test_geometry(std::string const & wkt,std::string const & expected_wkt,DistanceMeasure distance)150 void test_geometry(std::string const& wkt,
151 std::string const& expected_wkt,
152 DistanceMeasure distance)
153 {
154 typedef typename bg::point_type<Geometry>::type point_type;
155
156 Geometry geometry, expected;
157
158 bg::read_wkt(wkt, geometry);
159 bg::read_wkt(expected_wkt, expected);
160
161 boost::variant<Geometry> v(geometry);
162
163 // Define default strategy for testing
164 typedef bg::strategy::simplify::douglas_peucker
165 <
166 typename bg::point_type<Geometry>::type,
167 bg::strategy::distance::projected_point<double>
168 > dp;
169
170 check_geometry(geometry, expected, distance);
171 check_geometry(v, expected, distance);
172
173
174 BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy<dp, point_type>) );
175
176 check_geometry(geometry, expected, distance, dp());
177 check_geometry(v, expected, distance, dp());
178
179 // Check inserter (if applicable)
180 test_inserter
181 <
182 typename bg::tag<Geometry>::type
183 >::apply(geometry, expected, distance);
184
185 #ifdef TEST_PULL89
186 // Check using non-default less comparator in douglass_peucker
187 typedef typename bg::strategy::distance::detail::projected_point_ax<>::template result_type<point_type, point_type>::type distance_type;
188 typedef bg::strategy::distance::detail::projected_point_ax_less<distance_type> less_comparator;
189
190 distance_type const max_distance(distance);
191 less_comparator const less(max_distance);
192
193 typedef bg::strategy::simplify::detail::douglas_peucker
194 <
195 point_type,
196 bg::strategy::distance::detail::projected_point_ax<>,
197 less_comparator
198 > douglass_peucker_with_less;
199
200 BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy<douglass_peucker_with_less, point_type>) );
201
202 check_geometry(geometry, expected, distance, douglass_peucker_with_less(less));
203 check_geometry(v, expected, distance, douglass_peucker_with_less(less));
204 #endif
205 }
206
207 template <typename Geometry, typename Strategy, typename DistanceMeasure>
test_geometry(std::string const & wkt,std::string const & expected_wkt,DistanceMeasure const & distance,Strategy const & strategy)208 void test_geometry(std::string const& wkt,
209 std::string const& expected_wkt,
210 DistanceMeasure const& distance,
211 Strategy const& strategy)
212 {
213 Geometry geometry, expected;
214
215 bg::read_wkt(wkt, geometry);
216 bg::read_wkt(expected_wkt, expected);
217 bg::correct_closure(geometry);
218 bg::correct_closure(expected);
219
220 boost::variant<Geometry> v(geometry);
221
222 BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy<Strategy,
223 typename bg::point_type<Geometry>::type>) );
224
225 check_geometry(geometry, expected, distance, strategy);
226 check_geometry(v, expected, distance, strategy);
227 }
228
229 template <typename Geometry, typename DistanceMeasure>
test_geometry(std::string const & wkt,double expected_area,DistanceMeasure const & distance)230 void test_geometry(std::string const& wkt,
231 double expected_area,
232 DistanceMeasure const& distance)
233 {
234 Geometry geometry;
235 bg::read_wkt(wkt, geometry);
236 bg::correct_closure(geometry);
237
238 check_geometry_with_area(geometry, expected_area, distance);
239 }
240
241 #endif
242