1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2014-2017, Oracle and/or its affiliates.
4 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
5 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
6 
7 // Licensed under the Boost Software License version 1.0.
8 // http://www.boost.org/users/license.html
9 
10 
11 #ifndef BOOST_GEOMETRY_TEST_DIFFERENCE_LINEAR_LINEAR_HPP
12 #define BOOST_GEOMETRY_TEST_DIFFERENCE_LINEAR_LINEAR_HPP
13 
14 #include <limits>
15 
16 #include <boost/geometry/geometry.hpp>
17 #include "../test_set_ops_linear_linear.hpp"
18 #include "../check_turn_less.hpp"
19 #include <from_wkt.hpp>
20 #include <to_svg.hpp>
21 
22 
23 //==================================================================
24 //==================================================================
25 // difference of (linear) geometries
26 //==================================================================
27 //==================================================================
28 
29 template <typename Geometry1, typename Geometry2, typename MultiLineString>
check_result(Geometry1 const & geometry1,Geometry2 const & geometry2,MultiLineString const & mls_output,MultiLineString const & mls_diff,std::string const & case_id,double tolerance=std::numeric_limits<double>::epsilon ())30 inline void check_result(Geometry1 const& geometry1,
31                          Geometry2 const& geometry2,
32                          MultiLineString const& mls_output,
33                          MultiLineString const& mls_diff,
34                          std::string const& case_id,
35                          double tolerance = std::numeric_limits<double>::epsilon())
36 {
37     BOOST_CHECK_MESSAGE( equals::apply(mls_diff, mls_output, tolerance),
38                          "case id: " << case_id
39                          << ", difference L/L: " << bg::wkt(geometry1)
40                          << " " << bg::wkt(geometry2)
41                          << " -> Expected: " << bg::wkt(mls_diff)
42                          << std::setprecision(20)
43                          << " computed: " << bg::wkt(mls_output) );
44 }
45 
46 template
47 <
48     typename Geometry1, typename Geometry2,
49     typename MultiLineString
50 >
51 class test_difference_of_geometries
52 {
53 private:
base_test(Geometry1 const & geometry1,Geometry2 const & geometry2,MultiLineString const & mls_diff,std::string const & case_id,double tolerance,bool test_vector_and_deque=true,bool reverse_output_for_checking=false)54     static inline void base_test(Geometry1 const& geometry1,
55                                  Geometry2 const& geometry2,
56                                  MultiLineString const& mls_diff,
57                                  std::string const& case_id,
58                                  double tolerance,
59                                  bool test_vector_and_deque = true,
60                                  bool reverse_output_for_checking = false)
61     {
62         static bool vector_deque_already_tested = false;
63 
64         typedef typename boost::range_value<MultiLineString>::type LineString;
65         typedef std::vector<LineString> linestring_vector;
66         typedef std::deque<LineString> linestring_deque;
67 
68         MultiLineString mls_output;
69 
70         linestring_vector ls_vector_output;
71         linestring_deque ls_deque_output;
72 
73         // Check strategy passed explicitly
74         typedef typename bg::strategy::relate::services::default_strategy
75             <
76                 Geometry1, Geometry2
77             >::type strategy_type;
78         bg::difference(geometry1, geometry2, mls_output, strategy_type());
79 
80         if (reverse_output_for_checking)
81         {
82             bg::reverse(mls_output);
83         }
84 
85         check_result(geometry1, geometry2, mls_output, mls_diff, case_id, tolerance);
86 
87         // Check normal behaviour
88         bg::clear(mls_output);
89         bg::difference(geometry1, geometry2, mls_output);
90 
91         if ( reverse_output_for_checking )
92         {
93             bg::reverse(mls_output);
94         }
95 
96         check_result(geometry1, geometry2, mls_output, mls_diff, case_id, tolerance);
97 
98         set_operation_output("difference", case_id,
99                              geometry1, geometry2, mls_output);
100 
101         if ( !vector_deque_already_tested && test_vector_and_deque )
102         {
103             vector_deque_already_tested = true;
104 #ifdef BOOST_GEOMETRY_TEST_DEBUG
105             std::cout << std::endl;
106             std::cout << "Testing with vector and deque as output container..."
107                       << std::endl;
108 #endif
109             bg::difference(geometry1, geometry2, ls_vector_output);
110             bg::difference(geometry1, geometry2, ls_deque_output);
111 
112             BOOST_CHECK(multilinestring_equals
113                         <
114                             false
115                         >::apply(mls_diff, ls_vector_output, tolerance));
116 
117             BOOST_CHECK(multilinestring_equals
118                         <
119                             false
120                         >::apply(mls_diff, ls_deque_output, tolerance));
121 
122 #ifdef BOOST_GEOMETRY_TEST_DEBUG
123             std::cout << "Done!" << std::endl << std::endl;
124 #endif
125         }
126 
127 #ifdef BOOST_GEOMETRY_TEST_DEBUG
128         std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
129         std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
130         std::cout << "difference : " << bg::wkt(mls_output) << std::endl;
131         std::cout << "expected difference : " << bg::wkt(mls_diff) << std::endl;
132         std::cout << std::endl;
133         std::cout << "************************************" << std::endl;
134         std::cout << std::endl;
135         std::cout << std::endl;
136 #endif
137 
138         check_turn_less::apply(geometry1, geometry2);
139     }
140 
141 
142 public:
apply(Geometry1 const & geometry1,Geometry2 const & geometry2,MultiLineString const & mls_diff,std::string const & case_id,double tolerance=std::numeric_limits<double>::epsilon ())143     static inline void apply(Geometry1 const& geometry1,
144                              Geometry2 const& geometry2,
145                              MultiLineString const& mls_diff,
146                              std::string const& case_id,
147                              double tolerance
148                                  = std::numeric_limits<double>::epsilon())
149     {
150 #ifdef BOOST_GEOMETRY_TEST_DEBUG
151         std::cout << "test case: " << case_id << std::endl;
152         std::stringstream sstr;
153         sstr << "svgs/" << case_id << ".svg";
154 #ifdef TEST_WITH_SVG
155         to_svg(geometry1, geometry2, sstr.str());
156 #endif
157 #endif
158 
159         Geometry1 rg1(geometry1);
160         bg::reverse<Geometry1>(rg1);
161 
162         Geometry2 rg2(geometry2);
163         bg::reverse<Geometry2>(rg2);
164 
165         test_get_turns_ll_invariance<>::apply(geometry1, geometry2);
166 #ifdef BOOST_GEOMETRY_TEST_DEBUG
167         std::cout << std::endl
168                   << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
169                   << std::endl << std::endl;
170 #endif
171         test_get_turns_ll_invariance<>::apply(rg1, geometry2);
172 
173         base_test(geometry1, geometry2, mls_diff, case_id, tolerance);
174         base_test(geometry1, rg2, mls_diff, case_id, tolerance, false);
175         base_test(rg1, geometry2, mls_diff, case_id, tolerance, false, true);
176         base_test(rg1, rg2, mls_diff, case_id, tolerance, false, true);
177 
178 #ifdef BOOST_GEOMETRY_TEST_DEBUG
179         std::cout << std::endl;
180         std::cout << std::endl;
181 #endif
182     }
183 };
184 
185 
186 #endif // BOOST_GEOMETRY_TEST_DIFFERENCE_LINEAR_LINEAR_HPP
187