1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 
4 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
5 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
6 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
7 // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
8 
9 // Use, modification and distribution is subject to the Boost Software License,
10 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12 
13 #include <iostream>
14 #include <iomanip>
15 #include <string>
16 
17 // Instead of having a separate (and nearly similar) unit test to test multipolygons,
18 // we now include them here and compile them by default. Only undefining the next line
19 // will avoid testing multi-geometries
20 #define BOOST_GEOMETRY_UNIT_TEST_MULTI
21 
22 #include <boost/variant/variant.hpp>
23 
24 #include <geometry_test_common.hpp>
25 
26 // The include to test
27 #include <boost/geometry/algorithms/remove_spikes.hpp>
28 
29 // Helper includes
30 #include <boost/geometry/algorithms/area.hpp>
31 #include <boost/geometry/algorithms/correct.hpp>
32 #include <boost/geometry/algorithms/perimeter.hpp>
33 #include <boost/geometry/geometries/geometries.hpp>
34 #include <boost/geometry/geometries/point_xy.hpp>
35 #include <boost/geometry/io/wkt/wkt.hpp>
36 #include <boost/geometry/strategies/strategies.hpp>
37 
38 #if defined(BOOST_GEOMETRY_UNIT_TEST_MULTI)
39 #  include <boost/geometry/geometries/multi_polygon.hpp>
40 #endif
41 
42 
43 #if defined(TEST_WITH_SVG)
44 #  include <boost/geometry/io/svg/svg_mapper.hpp>
45 #endif
46 
47 
48 template <typename Geometry>
test_remove_spikes(std::string const &,Geometry & geometry,double expected_area,double expected_perimeter)49 inline void test_remove_spikes(std::string const& /*id*/,
50             Geometry& geometry,
51             double expected_area, double expected_perimeter)
52 {
53     bg::remove_spikes(geometry);
54 
55     double detected_area = bg::area(geometry);
56     double detected_perimeter = bg::perimeter(geometry);
57 
58     BOOST_CHECK_CLOSE(detected_area, expected_area, 0.01);
59     BOOST_CHECK_CLOSE(detected_perimeter, expected_perimeter, 0.01);
60 }
61 
62 template <typename Geometry>
test_geometry(std::string const & id,std::string const & wkt,double expected_area,double expected_perimeter)63 void test_geometry(std::string const& id, std::string const& wkt,
64             double expected_area, double expected_perimeter)
65 {
66     Geometry geometry;
67     bg::read_wkt(wkt, geometry);
68     bg::correct(geometry);
69     boost::variant<Geometry> v(geometry);
70 
71 #if defined(TEST_WITH_SVG)
72     std::ostringstream filename;
73     filename << "remove_spikes_" << id;
74     if (! bg::closure<Geometry>::value)
75     {
76         filename << "_open";
77     }
78     filename << ".svg";
79     std::ofstream svg(filename.str().c_str());
80 
81     bg::svg_mapper<typename bg::point_type<Geometry>::type> mapper(svg, 500, 500);
82     mapper.add(geometry);
83     mapper.map(geometry, "fill-opacity:0.3;opacity:0.6;fill:rgb(51,51,153);stroke:rgb(0,0,255);stroke-width:2");
84 #endif
85 
86     test_remove_spikes(id, geometry, expected_area, expected_perimeter);
87     test_remove_spikes(id, v, expected_area, expected_perimeter);
88 
89 #if defined(TEST_WITH_SVG)
90     mapper.map(geometry, "opacity:0.6;fill:none;stroke:rgb(255,0,0);stroke-width:3");
91 #endif
92 }
93 
94 template <typename P, bool Clockwise, bool Closed>
test_polygons()95 void test_polygons()
96 {
97     typedef bg::model::ring<P, Clockwise, Closed> ring;
98     typedef bg::model::polygon<P, Clockwise, Closed> polygon;
99 
100     test_geometry<ring>("box",
101             "POLYGON((0 0,0 4,4 4,4 0,0 0))",
102             16, 16);
103     test_geometry<polygon>("box",
104             "POLYGON((0 0,0 4,4 4,4 0,0 0))",
105             16, 16);
106     test_geometry<polygon>("box2",
107             "POLYGON((0 0,0 2,0 4,2 4,4 4,4 2,4 0,2 0,0 0))",
108             16, 16);
109     test_geometry<polygon>("spike_right",
110             "POLYGON((0 0,0 4,4 4,4 2,6 2,4 2,4 0,0 0))",
111             16, 16);
112     test_geometry<polygon>("spike_at_corner",
113             "POLYGON((0 0,0 4,6 4,4 4,4 0,0 0))",
114             16, 16);
115     test_geometry<polygon>("spike_at_first",
116             "POLYGON((0 0,-1 3,0 0,0 4,4 4,4 0,0 0))",
117             16, 16);
118     test_geometry<polygon>("spike_at_last",
119             "POLYGON((0 0,0 4,4 4,4 0,6 0,0 0))",
120             16, 16);
121     test_geometry<polygon>("spike_at_closing",
122             "POLYGON((-1 0,0 0,0 4,4 4,4 0,0 0,-1 0))",
123             16, 16);
124     test_geometry<polygon>("double_spike",
125             "POLYGON((0 0,0 4,4 4,4 2,6 2,5 2,4 2,4 0,0 0))",
126             16, 16);
127     test_geometry<polygon>("three_double_spike",
128             "POLYGON((0 0,0 4,4 4,4 2,6 2,5 2,4.5 2,4 2,4 0,0 0))",
129             16, 16);
130     test_geometry<polygon>("spike_with_corner",
131             "POLYGON((0 0,0 4,4 4,4 2,6 2,6 4,6 2,4 2,4 0,0 0))",
132             16, 16);
133 
134     test_geometry<polygon>("triangle0",
135             "POLYGON((0 0,0 4,2 0,4 0,0 0))",
136             4, 6 + sqrt(20.0));
137     test_geometry<polygon>("triangle1",
138             "POLYGON((0 4,2 0,4 0,0 0,0 4))",
139             4, 6 + sqrt(20.0));
140     test_geometry<polygon>("triangle2",
141             "POLYGON((2 0,4 0,0 0,0 4,2 0))",
142             4, 6 + sqrt(20.0));
143     test_geometry<polygon>("triangle3",
144             "POLYGON((4 0,0 0,0 4,2 0,4 0))",
145             4, 6 + sqrt(20.0));
146 
147     test_geometry<polygon>("only_spike1",
148             "POLYGON((0 0,2 2,0 0))",
149             0, 0);
150     test_geometry<polygon>("only_spike2",
151             "POLYGON((0 0,2 2,4 4,2 2,0 0))",
152             0, 0);
153     test_geometry<polygon>("only_spike3",
154             "POLYGON((0 0,2 2,4 4,0 0))",
155             0, 0);
156     test_geometry<polygon>("only_spike4",
157             "POLYGON((0 0,4 4,2 2,0 0))",
158             0, 0);
159 }
160 
161 
162 template <typename P, bool Clockwise, bool Closed>
test_multi_polygons()163 void test_multi_polygons()
164 {
165     typedef bg::model::polygon<P, Clockwise, Closed> polygon;
166     typedef bg::model::multi_polygon<polygon> multi_polygon;
167 
168     test_geometry<multi_polygon>("multi_spike_with_corner",
169             "MULTIPOLYGON(((0 0,0 4,4 4,4 2,6 2,6 4,6 2,4 2,4 0,0 0)))",
170             16, 16);
171 }
172 
173 template <typename P, bool Clockwise, bool Closed>
test_all()174 void test_all()
175 {
176     test_polygons<P, Clockwise, Closed>();
177     test_multi_polygons<P, Clockwise, Closed>();
178 }
179 
test_main(int,char * [])180 int test_main(int, char* [])
181 {
182     test_all<bg::model::d2::point_xy<double>, true, true>();
183     test_all<bg::model::d2::point_xy<double>, true, false>();
184     return 0;
185 }
186 
187