1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6 
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
9 
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13 
14 #include <algorithm>
15 #include <ostream>
16 #include <sstream>
17 #include <string>
18 #include <vector>
19 
20 #include <boost/config.hpp>
21 #include <geometry_test_common.hpp>
22 
23 #include <boost/geometry/algorithms/correct.hpp>
24 #include <boost/geometry/algorithms/within.hpp>
25 #include <boost/geometry/algorithms/intersection_segment.hpp>
26 #include <boost/geometry/io/wkt/aswkt.hpp>
27 
operator <<(std::ostream & s,const bg::intersection_result & r)28 static std::ostream & operator<<(std::ostream &s, const bg::intersection_result& r)
29 {
30     switch(r)
31     {
32         case bg::is_intersect_no : s << "is_intersect_no"; break;
33         case bg::is_intersect : s << "is_intersect"; break;
34         case bg::is_parallel : s << "is_parallel"; break;
35         case bg::is_collinear_no : s << "is_collinear_no"; break;
36         case bg::is_collinear_one : s << "is_collinear_one"; break;
37         case bg::is_collinear_connect : s << "is_collinear_connect"; break;
38         case bg::is_collinear_overlap : s << "is_collinear_overlap"; break;
39         case bg::is_collinear_overlap_opposite : s << "is_collinear_overlap_opposite"; break;
40         case bg::is_collinear_connect_opposite : s << "is_collinear_connect_opposite"; break;
41 
42         // detailed connection results:
43         case bg::is_intersect_connect_s1p1 : s << "is_intersect_connect_s1p1"; break;
44         case bg::is_intersect_connect_s1p2 : s << "is_intersect_connect_s1p2"; break;
45         case bg::is_intersect_connect_s2p1 : s << "is_intersect_connect_s2p1"; break;
46         case bg::is_intersect_connect_s2p2 : s << "is_intersect_connect_s2p2"; break;
47     }
48     return s;
49 }
50 
as_string(const bg::intersection_result & r)51 static std::string as_string(const bg::intersection_result& r)
52 {
53     std::stringstream out;
54     out << r;
55     return out.str();
56 }
57 
58 typedef bg::model::point<double> P;
59 typedef bg::const_segment<P> S;
60 
61 
test_intersection(double s1x1,double s1y1,double s1x2,double s1y2,double s2x1,double s2y1,double s2x2,double s2y2,bg::intersection_result expected_result,int exptected_count,const P & exp_p1,const P & exp_p2)62 static void test_intersection(double s1x1, double s1y1, double s1x2, double s1y2,
63                        double s2x1, double s2y1, double s2x2, double s2y2,
64                        // Expected results
65                        bg::intersection_result expected_result,
66                        int exptected_count, const P& exp_p1, const P& exp_p2)
67 {
68     S s1(P(s1x1, s1y1), P(s1x2, s1y2));
69     S s2(P(s2x1, s2y1), P(s2x2, s2y2));
70     std::vector<P> ip;
71     double ra, rb;
72     bg::intersection_result r = bg::intersection_s(s1, s2, ra, rb, ip);
73     r = bg::intersection_connect_result(r, ra, rb);
74 
75     BOOST_CHECK_EQUAL(ip.size(), exptected_count);
76     BOOST_CHECK_EQUAL(as_string(expected_result), as_string(r));
77 
78     if (ip.size() == 2 && ip[0] != exp_p1)
79     {
80         // Swap results, second point is not as expected, swap results, order is not prescribed,
81         // it might be OK.
82         std::reverse(ip.begin(), ip.end());
83     }
84 
85     if (ip.size() >= 1)
86     {
87         BOOST_CHECK_EQUAL(ip[0], exp_p1);
88     }
89     if (ip.size() >= 2)
90     {
91         BOOST_CHECK_EQUAL(ip[1], exp_p2);
92     }
93 
94 
95     /*
96     std::cout << exptected_count << " " << r;
97     if (exptected_count >= 1) std::cout << " " << ip[0];
98     if (exptected_count >= 2) std::cout << " " << ip[1];
99     std::cout << std::endl;
100     */
101 }
102 
103 //BOOST_AUTO_TEST_CASE( test1 )
test_main(int,char * [])104 int test_main( int , char* [] )
105 {
106     // Identical cases
107     test_intersection(0,0, 1,1,  0,0, 1,1,          bg::is_collinear_overlap, 2,  P(0,0), P(1,1));
108     test_intersection(1,1, 0,0,  0,0, 1,1,          bg::is_collinear_overlap_opposite, 2,  P(1,1), P(0,0));
109     test_intersection(0,1, 0,2,  0,1, 0,2,          bg::is_collinear_overlap, 2,  P(0,1), P(0,2)); // Vertical
110     test_intersection(0,2, 0,1,  0,1, 0,2,          bg::is_collinear_overlap_opposite, 2,  P(0,2), P(0,1)); // Vertical
111     // Overlap cases
112     test_intersection(0,0, 1,1,  -0.5,-0.5, 2,2,    bg::is_collinear_overlap, 2,  P(0,0), P(1,1));
113     test_intersection(0,0, 1,1,  0.5,0.5, 1.5,1.5,  bg::is_collinear_overlap, 2,  P(0.5,0.5), P(1,1));
114     test_intersection(0,0, 0,1,  0,-10, 0,10,       bg::is_collinear_overlap, 2,  P(0,0), P(0,1)); // Vertical
115     test_intersection(0,0, 0,1,  0,10, 0,-10,       bg::is_collinear_overlap_opposite, 2,  P(0,0), P(0,1)); // Vertical
116     test_intersection(0,0, 1,1,  1,1, 2,2,          bg::is_collinear_connect, 1,  P(1,1), P(0,0)); // Single point
117     // Colinear, non overlap cases
118     test_intersection(0,0, 1,1,  1.5,1.5, 2.5,2.5,  bg::is_collinear_no, 0,  P(0,0), P(0,0));
119     test_intersection(0,0, 0,1,  0,5, 0,6,          bg::is_collinear_no, 0,  P(0,0), P(0,0)); // Vertical
120     // Parallel cases
121     test_intersection(0,0, 1,1,  1,0, 2,1,       bg::is_parallel, 0,  P(0,0), P(0,1));
122     // Intersect cases
123     test_intersection(0,2, 4,2,  3,0, 3,4,       bg::is_intersect, 1,  P(3,2), P(0,0));
124     // Non intersect cases
125 
126     // Single point cases
127     test_intersection(0,0, 0,0,  1,1, 2,2,          bg::is_collinear_no, 0,  P(1,1), P(0,0)); // Colinear/no
128     test_intersection(2,2, 2,2,  1,1, 3,3,          bg::is_collinear_one, 1,  P(2,2.01), P(0,0)); // On segment
129     test_intersection(1,1, 3,3,  2,2, 2,2,          bg::is_collinear_one, 1,  P(2,2), P(0,0)); // On segment
130     test_intersection(1,1, 3,3,  1,1, 1,1,          bg::is_collinear_one, 1,  P(1,1), P(0,0)); // On segment, start
131     test_intersection(1,1, 3,3,  3,3, 3,3,          bg::is_collinear_one, 1,  P(3,3), P(0,0)); // On segment, end
132 
133     return 0;
134 }
135