Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / geometry / test / arithmetic / infinite_line_functions.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands.
5
6 // This file was modified by Oracle on 2019.
7 // Modifications copyright (c) 2019, Oracle and/or its affiliates.
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
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 <geometry_test_common.hpp>
15
16 #include <boost/geometry/arithmetic/infinite_line_functions.hpp>
17 #include <boost/geometry/geometries/infinite_line.hpp>
18 #include <boost/geometry/algorithms/detail/make/make.hpp>
19 #include <boost/geometry/geometries/point.hpp>
20 #include <boost/geometry/io/wkt/wkt.hpp>
21
22 namespace
23 {
24     // Boost.Test does not support BOOST_CHECK_CLOSE for integral types
25     template <typename T>
26     bool is_small(T const& value)
27     {
28         static long double const epsilon = 1.0e-5;
29         return bg::math::abs(value) < epsilon;
30     }
31 }
32
33 template <typename T, typename C>
34 void verify_point_on_line(bg::model::infinite_line<T> const& line,
35                           C const& x, C const& y)
36 {
37     BOOST_CHECK_MESSAGE(is_small(line.a * x + line.b * y + line.c),
38                         "Point is not located on the line");
39 }
40
41 template <typename T>
42 void test_side_value()
43 {
44     typedef bg::model::infinite_line<T> line_type;
45
46     // Horizontal line going right
47     line_type line = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
48
49     // Point above (= on left side)
50     T d = bg::arithmetic::side_value(line, 5, 5);
51     BOOST_CHECK_MESSAGE(d > 0, "point not on left side");
52
53     // Point below (= on right side)
54     d = bg::arithmetic::side_value(line, 5, -5);
55     BOOST_CHECK_MESSAGE(d < 0, "point not on right side");
56
57     // Diagonal not through origin, from right (down) to left (up)
58     line = bg::detail::make::make_infinite_line<T>(5, 2, -7, 10);
59     d = bg::arithmetic::side_value(line, 5, 2);
60     BOOST_CHECK_MESSAGE(is_small(d), "point not on line");
61     d = bg::arithmetic::side_value(line, -7, 10);
62     BOOST_CHECK_MESSAGE(is_small(d), "point not on line");
63
64     // vector is (-12, 8), move (-3,2) on the line from (5,2)
65     d = bg::arithmetic::side_value(line, 2, 4);
66     BOOST_CHECK_MESSAGE(is_small(d), "point not on line");
67
68     // Go perpendicular (2,3) from (2,4) up, so right of the line (negative)
69     d = bg::arithmetic::side_value(line, 4, 7);
70     BOOST_CHECK_MESSAGE(d < 0, "point not on right side");
71
72     // Go perpendicular (2,3) from (2,4) down, so left of the line (positive)
73     d = bg::arithmetic::side_value(line, 0, 1);
74     BOOST_CHECK_MESSAGE(d > 0, "point not on left side");
75 }
76
77
78 template <typename T>
79 void test_get_intersection()
80 {
81     typedef bg::model::infinite_line<T> line_type;
82
83     // Diagonal lines (first is same as in distance measure,
84     // second is perpendicular and used there for distance measures)
85     line_type p = bg::detail::make::make_infinite_line<T>(5, 2, -7, 10);
86     line_type q = bg::detail::make::make_infinite_line<T>(4, 7, 0, 1);
87
88     typedef bg::model::point<T, 2, bg::cs::cartesian> point_type;
89     point_type ip;
90     BOOST_CHECK(bg::arithmetic::intersection_point(p, q, ip));
91
92     BOOST_CHECK_MESSAGE(is_small(bg::get<0>(ip) - 2), "x-coordinate wrong");
93     BOOST_CHECK_MESSAGE(is_small(bg::get<1>(ip) - 4), "y-coordinate wrong");
94
95     verify_point_on_line(p, bg::get<0>(ip), bg::get<1>(ip));
96     verify_point_on_line(q, bg::get<0>(ip), bg::get<1>(ip));
97 }
98
99 template <typename T>
100 void test_same_direction()
101 {
102     bg::model::infinite_line<T> p, q;
103
104     // Exactly opposite, diagonal
105     p = bg::detail::make::make_infinite_line<T>(2, 1, 12, 11);
106     q = bg::detail::make::make_infinite_line<T>(12, 11, 2, 1);
107     BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
108
109     // Exactly opposite, horizontal
110     p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
111     q = bg::detail::make::make_infinite_line<T>(10, 0, 0, 0);
112     BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
113
114     // Exactly opposite, vertical
115     p = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
116     q = bg::detail::make::make_infinite_line<T>(0, 10, 0, 0);
117     BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
118
119     // Exactly equal, diagonal
120     p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
121     q = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
122     BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
123
124     // Exactly equal, horizontal
125     p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
126     q = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
127     BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
128
129     // Exactly equal, vertical
130     p = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
131     q = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
132     BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
133
134     // Coming together, diagonal
135     p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
136     q = bg::detail::make::make_infinite_line<T>(20, 20, 10, 10);
137     BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
138
139     // Leaving from common point, diagonal
140     p = bg::detail::make::make_infinite_line<T>(10, 10, 0, 0);
141     q = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
142     BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
143
144     // Continuing each other, diagonal
145     p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
146     q = bg::detail::make::make_infinite_line<T>(10, 10, 20, 20);
147     BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
148
149     // (Nearly) perpendicular
150     p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
151     q = bg::detail::make::make_infinite_line<T>(0, 0, -10, 10);
152     BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
153
154     // 45 deg
155     p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
156     q = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
157     BOOST_CHECK(bg::arithmetic::similar_direction(p, q));
158
159     // a bit more than 45 deg
160     p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
161     q = bg::detail::make::make_infinite_line<T>(0, 0, -1, 10);
162     BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
163
164     // 135 deg
165     p = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
166     q = bg::detail::make::make_infinite_line<T>(0, 0, -10, 0);
167     BOOST_CHECK(! bg::arithmetic::similar_direction(p, q));
168 }
169
170 template <typename T>
171 void test_degenerate()
172 {
173     typedef bg::model::infinite_line<T> line_type;
174
175     line_type line = bg::detail::make::make_infinite_line<T>(0, 0, 10, 0);
176     BOOST_CHECK(! bg::arithmetic::is_degenerate(line));
177
178     line = bg::detail::make::make_infinite_line<T>(0, 0, 0, 10);
179     BOOST_CHECK(! bg::arithmetic::is_degenerate(line));
180
181     line = bg::detail::make::make_infinite_line<T>(0, 0, 10, 10);
182     BOOST_CHECK(! bg::arithmetic::is_degenerate(line));
183
184     line = bg::detail::make::make_infinite_line<T>(0, 0, 0, 0);
185     BOOST_CHECK(bg::arithmetic::is_degenerate(line));
186 }
187
188
189 template <typename T>
190 void test_all()
191 {
192     test_side_value<T>();
193     test_get_intersection<T>();
194     test_same_direction<T>();
195     test_degenerate<T>();
196 }
197
198 int test_main(int, char* [])
199 {
200     test_all<double>();
201     test_all<long double>();
202     test_all<float>();
203     test_all<int>();
204     return 0;
205 }