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