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_INTERSECTION_LINEAR_LINEAR_HPP
12 #define BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP
13 
14 #include <limits>
15 
16 #include <boost/type_traits/is_same.hpp>
17 
18 #include <boost/geometry/geometry.hpp>
19 #include "../test_set_ops_linear_linear.hpp"
20 #include <from_wkt.hpp>
21 #include <to_svg.hpp>
22 
23 
24 //==================================================================
25 //==================================================================
26 // intersection of (linear) geometries
27 //==================================================================
28 //==================================================================
29 
30 template <typename Geometry1, typename Geometry2, typename MultiLineString>
check_result(Geometry1 const & geometry1,Geometry2 const & geometry2,MultiLineString const & mls_output,MultiLineString const & mls_int1,MultiLineString const & mls_int2,std::string const & case_id,double tolerance)31 inline void check_result(Geometry1 const& geometry1,
32                          Geometry2 const& geometry2,
33                          MultiLineString const& mls_output,
34                          MultiLineString const& mls_int1,
35                          MultiLineString const& mls_int2,
36                          std::string const& case_id,
37                          double tolerance)
38 {
39     BOOST_CHECK_MESSAGE( equals::apply(mls_int1, mls_output, tolerance)
40                          || equals::apply(mls_int2, mls_output, tolerance),
41                          "case id: " << case_id
42                          << ", intersection L/L: " << bg::wkt(geometry1)
43                          << " " << bg::wkt(geometry2)
44                          << " -> Expected: " << bg::wkt(mls_int1)
45                          << " or: " << bg::wkt(mls_int2)
46                          << " computed: " << bg::wkt(mls_output) );
47 }
48 
49 template
50 <
51     typename Geometry1, typename Geometry2,
52     typename MultiLineString
53 >
54 class test_intersection_of_geometries
55 {
56 private:
base_test(Geometry1 const & geometry1,Geometry2 const & geometry2,MultiLineString const & mls_int1,MultiLineString const & mls_int2,std::string const & case_id,double tolerance,bool test_vector_and_deque=false)57     static inline void base_test(Geometry1 const& geometry1,
58                                  Geometry2 const& geometry2,
59                                  MultiLineString const& mls_int1,
60                                  MultiLineString const& mls_int2,
61                                  std::string const& case_id,
62                                  double tolerance,
63                                  bool test_vector_and_deque = false)
64     {
65         static bool vector_deque_already_tested = false;
66 
67         typedef typename boost::range_value<MultiLineString>::type LineString;
68         typedef std::vector<LineString> linestring_vector;
69         typedef std::deque<LineString> linestring_deque;
70 
71         MultiLineString mls_output;
72 
73         linestring_vector ls_vector_output;
74         linestring_deque ls_deque_output;
75 
76         // Check normal behaviour
77         bg::intersection(geometry1, geometry2, mls_output);
78 
79         check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, case_id, tolerance);
80 
81         // Check strategy passed explicitly
82         typedef typename bg::strategy::relate::services::default_strategy
83             <
84                 Geometry1, Geometry2
85             >::type strategy_type;
86         bg::clear(mls_output);
87         bg::intersection(geometry1, geometry2, mls_output, strategy_type());
88 
89         check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, case_id, tolerance);
90 
91         set_operation_output("intersection", case_id,
92                              geometry1, geometry2, mls_output);
93 #ifdef BOOST_GEOMETRY_TEST_DEBUG
94         std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
95         std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
96         std::cout << "intersection : " << bg::wkt(mls_output) << std::endl;
97         std::cout << "expected intersection : " << bg::wkt(mls_int1)
98                   << " or: " << bg::wkt(mls_int2) << std::endl;
99         std::cout << std::endl;
100         std::cout << "************************************" << std::endl;
101         std::cout << std::endl;
102         std::cout << std::endl;
103 #endif
104 
105         if ( !vector_deque_already_tested && test_vector_and_deque )
106         {
107             vector_deque_already_tested = true;
108 #ifdef BOOST_GEOMETRY_TEST_DEBUG
109             std::cout << std::endl;
110             std::cout << "Testing with vector and deque as output container..."
111                       << std::endl;
112 #endif
113             bg::intersection(geometry1, geometry2, ls_vector_output);
114             bg::intersection(geometry1, geometry2, ls_deque_output);
115 
116             BOOST_CHECK(multilinestring_equals
117                         <
118                             false
119                         >::apply(mls_int1, ls_vector_output, tolerance));
120 
121             BOOST_CHECK(multilinestring_equals
122                         <
123                             false
124                         >::apply(mls_int1, ls_deque_output, tolerance));
125 
126 #ifdef BOOST_GEOMETRY_TEST_DEBUG
127             std::cout << "Done!" << std::endl << std::endl;
128 #endif
129         }
130 
131         // check the intersection where the order of the two
132         // geometries is reversed
133         bg::clear(mls_output);
134         bg::intersection(geometry2, geometry1, mls_output);
135 
136         check_result(geometry1, geometry2, mls_output, mls_int1, mls_int2, case_id, tolerance);
137 
138 #ifdef BOOST_GEOMETRY_TEST_DEBUG
139         std::cout << "Geometry #1: " << bg::wkt(geometry2) << std::endl;
140         std::cout << "Geometry #2: " << bg::wkt(geometry1) << std::endl;
141         std::cout << "intersection : " << bg::wkt(mls_output) << std::endl;
142         std::cout << "expected intersection : " << bg::wkt(mls_int1)
143                   << " or: " << bg::wkt(mls_int2) << std::endl;
144         std::cout << std::endl;
145         std::cout << "************************************" << std::endl;
146         std::cout << std::endl;
147         std::cout << std::endl;
148 #endif
149     }
150 
151 #ifdef BOOST_GEOMETRY_TEST_DEBUG
base_test_all(Geometry1 const & geometry1,Geometry2 const & geometry2)152     static inline void base_test_all(Geometry1 const& geometry1,
153                                      Geometry2 const& geometry2)
154     {
155         typedef typename bg::point_type<MultiLineString>::type Point;
156         typedef bg::model::multi_point<Point> multi_point;
157 
158         MultiLineString mls12_output, mls21_output;
159         multi_point mp12_output, mp21_output;
160 
161         bg::intersection(geometry1, geometry2, mls12_output);
162         bg::intersection(geometry1, geometry2, mp12_output);
163         bg::intersection(geometry2, geometry1, mls21_output);
164         bg::intersection(geometry2, geometry1, mp21_output);
165 
166         std::cout << "************************************" << std::endl;
167         std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
168         std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
169         std::cout << "intersection(1,2) [MLS]: " << bg::wkt(mls12_output)
170                   << std::endl;
171         std::cout << "intersection(2,1) [MLS]: " << bg::wkt(mls21_output)
172                   << std::endl;
173         std::cout << std::endl;
174         std::cout << "intersection(1,2) [MP]: " << bg::wkt(mp12_output)
175                   << std::endl;
176         std::cout << "intersection(2,1) [MP]: " << bg::wkt(mp21_output)
177                   << std::endl;
178         std::cout << std::endl;
179         std::cout << "************************************" << std::endl;
180         std::cout << std::endl;
181         std::cout << std::endl;
182     }
183 #else
base_test_all(Geometry1 const &,Geometry2 const &)184     static inline void base_test_all(Geometry1 const&, Geometry2 const&)
185     {
186     }
187 #endif
188 
189 
190 public:
apply(Geometry1 const & geometry1,Geometry2 const & geometry2,MultiLineString const & mls_int1,MultiLineString const & mls_int2,std::string const & case_id,double tolerance=std::numeric_limits<double>::epsilon ())191     static inline void apply(Geometry1 const& geometry1,
192                              Geometry2 const& geometry2,
193                              MultiLineString const& mls_int1,
194                              MultiLineString const& mls_int2,
195                              std::string const& case_id,
196                              double tolerance
197                                  = std::numeric_limits<double>::epsilon())
198     {
199 #ifdef BOOST_GEOMETRY_TEST_DEBUG
200         std::cout << "test case: " << case_id << std::endl;
201         std::stringstream sstr;
202         sstr << "svgs/" << case_id << ".svg";
203 #ifdef TEST_WITH_SVG
204         to_svg(geometry1, geometry2, sstr.str());
205 #endif
206 #endif
207 
208         Geometry1 rg1(geometry1);
209         bg::reverse<Geometry1>(rg1);
210 
211         Geometry2 rg2(geometry2);
212         bg::reverse<Geometry2>(rg2);
213 
214         typedef typename bg::tag_cast
215             <
216                 Geometry1, bg::linear_tag
217             >::type tag1_type;
218 
219         typedef typename bg::tag_cast
220             <
221                 Geometry2, bg::linear_tag
222             >::type tag2_type;
223 
224         bool const are_linear
225             = boost::is_same<tag1_type, bg::linear_tag>::value
226             && boost::is_same<tag2_type, bg::linear_tag>::value;
227 
228         test_get_turns_ll_invariance<are_linear>::apply(geometry1, geometry2);
229 #ifdef BOOST_GEOMETRY_TEST_DEBUG
230         std::cout << std::endl
231                   << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
232                   << std::endl << std::endl;
233 #endif
234         test_get_turns_ll_invariance<are_linear>::apply(rg1, geometry2);
235 
236         base_test(geometry1, geometry2, mls_int1, mls_int2, case_id, tolerance);
237         //        base_test(rg1, rg2, mls_int1, mls_int2);
238         base_test_all(geometry1, geometry2);
239 
240 #ifdef BOOST_GEOMETRY_TEST_DEBUG
241         std::cout << std::endl;
242         std::cout << std::endl;
243 #endif
244     }
245 
246 
247 
apply(Geometry1 const & geometry1,Geometry2 const & geometry2,MultiLineString const & mls_int,std::string const & case_id,double tolerance=std::numeric_limits<double>::epsilon ())248     static inline void apply(Geometry1 const& geometry1,
249                              Geometry2 const& geometry2,
250                              MultiLineString const& mls_int,
251                              std::string const& case_id,
252                              double tolerance
253                                  = std::numeric_limits<double>::epsilon())
254     {
255         apply(geometry1, geometry2, mls_int, mls_int, case_id, tolerance);
256     }
257 };
258 
259 
260 #endif // BOOST_GEOMETRY_TEST_INTERSECTION_LINEAR_LINEAR_HPP
261