• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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