• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2014-2020, Oracle and/or its affiliates.
4 
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
6 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
7 
8 // Licensed under the Boost Software License version 1.0.
9 // http://www.boost.org/users/license.html
10 
11 #ifndef BOOST_GEOMETRY_TEST_SET_OPS_POINTLIKE_HPP
12 #define BOOST_GEOMETRY_TEST_SET_OPS_POINTLIKE_HPP
13 
14 
15 #include <boost/geometry/geometry.hpp>
16 
17 namespace bg = ::boost::geometry;
18 
19 #include <from_wkt.hpp>
20 #include <to_svg.hpp>
21 
22 #include <algorithm>
23 #include <fstream>
24 #include <boost/core/ignore_unused.hpp>
25 #include <boost/typeof/typeof.hpp>
26 
27 #include <boost/geometry/policies/compare.hpp>
28 #include <boost/geometry/algorithms/equals.hpp>
29 
30 #include <boost/geometry/algorithms/union.hpp>
31 #include <boost/geometry/algorithms/difference.hpp>
32 #include <boost/geometry/algorithms/intersection.hpp>
33 #include <boost/geometry/algorithms/sym_difference.hpp>
34 
35 #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
36 
37 
38 //==================================================================
39 //==================================================================
40 // svg output
41 //==================================================================
42 //==================================================================
43 
44 template <typename Output, typename G1, typename G2>
set_operation_output(std::string const & set_op_id,std::string const & caseid,G1 const & g1,G2 const & g2,Output const & output)45 void set_operation_output(std::string const& set_op_id,
46                           std::string const& caseid,
47                           G1 const& g1, G2 const& g2,
48                           Output const& output)
49 {
50     boost::ignore_unused(set_op_id, caseid, g1, g2, output);
51 
52 #if defined(TEST_WITH_SVG)
53     typedef typename bg::coordinate_type<G1>::type coordinate_type;
54     typedef typename bg::point_type<G1>::type point_type;
55 
56     std::ostringstream filename;
57     filename << "svgs/" << set_op_id << "_" << caseid << ".svg";
58 
59     std::ofstream svg(filename.str().c_str());
60 
61     bg::svg_mapper<point_type> mapper(svg, 500, 500);
62 
63     mapper.add(g1);
64     mapper.add(g2);
65 
66     mapper.map(g2, "stroke-opacity:1;stroke:rgb(153,204,0);stroke-width:4");
67     mapper.map(g1, "stroke-opacity:1;stroke:rgb(51,51,153);stroke-width:2");
68 
69     BOOST_AUTO_TPL(it, output.begin());
70     for (; it != output.end(); ++it)
71     {
72         mapper.map(*it,
73                    "fill:rgb(255,0,255);stroke:rgb(0,0,0);stroke-width:1",
74                    4);
75     }
76 #endif
77 }
78 
79 
80 //==================================================================
81 //==================================================================
82 // testing equality of multi-points
83 //==================================================================
84 //==================================================================
85 
86 
87 struct equals
88 {
89     template <typename MultiPoint1, typename MultiPoint2>
applyequals90     static inline bool apply(MultiPoint1 const& multipoint1,
91                              MultiPoint2 const& multipoint2)
92     {
93         MultiPoint1 mp1(multipoint1);
94         MultiPoint2 mp2(multipoint2);
95 
96         std::sort(mp1.begin(), mp1.end(),
97                   bg::less<typename bg::point_type<MultiPoint1>::type>());
98         std::sort(mp2.begin(), mp2.end(),
99                   bg::less<typename bg::point_type<MultiPoint2>::type>());
100 
101         if ( boost::size(mp1) != boost::size(mp2) )
102         {
103             return false;
104         }
105 
106         BOOST_AUTO_TPL(it1, boost::begin(mp1));
107         BOOST_AUTO_TPL(it2, boost::begin(mp2));
108         for (; it1 != boost::end(mp1); ++it1, ++it2)
109         {
110             if ( !bg::equals(*it1, *it2) )
111             {
112                 return false;
113             }
114         }
115         return true;
116     }
117 };
118 
119 
120 
121 //==================================================================
122 //==================================================================
123 // struct for calling the appropriate set op function
124 //==================================================================
125 //==================================================================
126 
127 template <bg::overlay_type OverlayType> struct set_op;
128 
129 
130 template<>
131 struct set_op<bg::overlay_difference>
132 {
nameset_op133     static inline std::string name() { return "difference"; }
134 
135     template <typename Geometry1, typename Geometry2, typename GeometryOut>
applyset_op136     static inline void apply(Geometry1 const& g1,
137                              Geometry2 const& g2,
138                              GeometryOut& gout)
139     {
140         bg::difference(g1, g2, gout);
141     }
142 };
143 
144 
145 template<>
146 struct set_op<bg::overlay_union>
147 {
nameset_op148     static inline std::string name() { return "union"; }
149 
150     template <typename Geometry1, typename Geometry2, typename GeometryOut>
applyset_op151     static inline void apply(Geometry1 const& g1,
152                              Geometry2 const& g2,
153                              GeometryOut& gout)
154     {
155         bg::union_(g1, g2, gout);
156     }
157 };
158 
159 
160 template<>
161 struct set_op<bg::overlay_intersection>
162 {
nameset_op163     static inline std::string name() { return "intersection"; }
164 
165     template <typename Geometry1, typename Geometry2, typename GeometryOut>
applyset_op166     static inline void apply(Geometry1 const& g1,
167                              Geometry2 const& g2,
168                              GeometryOut& gout)
169     {
170         bg::intersection(g1, g2, gout);
171     }
172 };
173 
174 
175 template
176 <
177     typename Geometry,
178     typename Tag = typename bg::tag<Geometry>::type
179 > struct geometry_info
180 {};
181 
182 template <typename Point>
183 struct geometry_info<Point, bg::point_tag>
184 {
185     static std::size_t const topological_dimension = 0;
186 
namegeometry_info187     static inline char const* name() { return "Pt"; }
188 };
189 
190 template <typename MultiPoint>
191 struct geometry_info<MultiPoint, bg::multi_point_tag>
192 {
193     static std::size_t const topological_dimension = 0;
194 
namegeometry_info195     static inline char const* name() { return "MPt"; }
196 };
197 
198 template <typename Linestring>
199 struct geometry_info<Linestring, bg::linestring_tag>
200 {
201     static std::size_t const topological_dimension = 1;
202 
namegeometry_info203     static inline char const* name() { return "L"; }
204 };
205 
206 template <typename MultiLinestring>
207 struct geometry_info<MultiLinestring, bg::multi_linestring_tag>
208 {
209     static std::size_t const topological_dimension = 1;
210 
namegeometry_info211     static inline char const* name() { return "ML"; }
212 };
213 
214 template <typename Segment>
215 struct geometry_info<Segment, bg::segment_tag>
216 {
217     static std::size_t const topological_dimension = 1;
218 
namegeometry_info219     static inline char const* name() { return "S"; }
220 };
221 
222 template <typename Ring>
223 struct geometry_info<Ring, bg::ring_tag>
224 {
225     static std::size_t const topological_dimension = 2;
226 
namegeometry_info227     static inline char const* name() { return "R"; }
228 };
229 
230 template <typename Polygon>
231 struct geometry_info<Polygon, bg::polygon_tag>
232 {
233     static std::size_t const topological_dimension = 2;
234 
namegeometry_info235     static inline char const* name() { return "Po"; }
236 };
237 
238 template <typename MultiPolygon>
239 struct geometry_info<MultiPolygon, bg::multi_polygon_tag>
240 {
241     static std::size_t const topological_dimension = 2;
242 
namegeometry_info243     static inline char const* name() { return "MPo"; }
244 };
245 
246 //==================================================================
247 //==================================================================
248 // test the set operation of (point-like) geometries
249 //==================================================================
250 //==================================================================
251 
252 
253 template
254 <
255     typename Geometry1,
256     typename Geometry2,
257     typename MultiPoint,
258     bg::overlay_type OverlayType
259 >
260 class test_set_op_of_pointlike_geometries
261 {
262 private:
263     template <bool Enable, typename Dummy = void>
264     struct base_test
265     {
266         template <typename G1, typename G2, typename MP>
applytest_set_op_of_pointlike_geometries::base_test267         static inline void apply(std::string const& case_id,
268                                  G1 const& geometry1,
269                                  G2 const& geometry2,
270                                  MP const& mp_expected)
271         {
272             MultiPoint mp_output;
273 
274             set_op<OverlayType>::apply(geometry1, geometry2, mp_output);
275 
276             std::string op_name = set_op<OverlayType>::name();
277 
278             BOOST_CHECK_MESSAGE(equals::apply(mp_expected, mp_output),
279                                 "case ID: " << case_id << ", "
280                                 << op_name << " "
281                                 << geometry_info<G1>::name() << "/"
282                                 << geometry_info<G2>::name() << ": "
283                                 << bg::wkt(geometry1)
284                                 << " " << bg::wkt(geometry2)
285                                 << " -> Expected: " << bg::wkt(mp_expected)
286                                 << " computed: " << bg::wkt(mp_output) );
287 
288             set_operation_output(op_name, case_id,
289                                  geometry1, geometry2, mp_output);
290 
291 #ifdef BOOST_GEOMETRY_TEST_DEBUG
292             std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
293             std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
294             std::cout << "expected " << op_name << " : "
295                       << bg::wkt(mp_expected) << std::endl;
296             std::cout << op_name << " : " << bg::wkt(mp_output) << std::endl;
297             std::cout << std::endl;
298             std::cout << "************************************" << std::endl;
299             std::cout << std::endl;
300             std::cout << std::endl;
301 #endif
302         }
303     };
304 
305     template <typename Dummy>
306     struct base_test<false, Dummy>
307     {
308         template <typename G1, typename G2, typename MP>
applytest_set_op_of_pointlike_geometries::base_test309         static inline void apply(std::string const&, G1 const&, G2 const&,
310                                  MP const&)
311         {
312         }
313     };
314 
315 public:
apply(std::string const & case_id,Geometry1 const & geometry1,Geometry2 const & geometry2,MultiPoint const & mp_expected12,MultiPoint const & mp_expected21)316     static inline void apply(std::string const& case_id,
317                              Geometry1 const& geometry1,
318                              Geometry2 const& geometry2,
319                              MultiPoint const& mp_expected12,
320                              MultiPoint const& mp_expected21)
321     {
322 #ifdef BOOST_GEOMETRY_TEST_DEBUG
323         std::cout << "test case: " << case_id << std::endl;
324 #endif
325 
326         base_test<true>::apply(case_id, geometry1, geometry2, mp_expected12);
327         // try the same set operation with the arguments' order
328         // reversed only if the two geometries are of the same
329         // topological dimension
330         base_test
331             <
332                 (geometry_info<Geometry1>::topological_dimension
333                  == geometry_info<Geometry2>::topological_dimension)
334             >::apply(case_id, geometry2, geometry1, mp_expected21);
335 
336 #ifdef BOOST_GEOMETRY_TEST_DEBUG
337         std::cout << std::endl;
338         std::cout << std::endl;
339 #endif
340     }
341 
apply(std::string const & case_id,Geometry1 const & geometry1,Geometry2 const & geometry2,MultiPoint const & mp_expected)342     static inline void apply(std::string const& case_id,
343                              Geometry1 const& geometry1,
344                              Geometry2 const& geometry2,
345                              MultiPoint const& mp_expected)
346     {
347         apply(case_id, geometry1, geometry2, mp_expected, mp_expected);
348     }
349 };
350 
351 
352 #endif // BOOST_GEOMETRY_TEST_SET_OPS_POINTLIKE_HPP
353