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 #ifndef BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
15 #define BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
16 
17 #include <cmath>
18 #include <utility>
19 
20 #if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
21 #  include <iostream>
22 #endif
23 
24 namespace boost { namespace geometry
25 {
26 
27 // Silence warning C4127: conditional expression is constant
28 #if defined(_MSC_VER)
29 #pragma warning(push)
30 #pragma warning(disable : 4127)
31 #endif
32 
33 /*!
34 \brief Class side_info: small class wrapping for sides (-1,0,1)
35 */
36 class side_info
37 {
38 public :
side_info(int side_a1=0,int side_a2=0,int side_b1=0,int side_b2=0)39     inline side_info(int side_a1 = 0, int side_a2 = 0,
40             int side_b1 = 0, int side_b2 = 0)
41     {
42         sides[0].first = side_a1;
43         sides[0].second = side_a2;
44         sides[1].first = side_b1;
45         sides[1].second = side_b2;
46     }
47 
48     template <int Which>
set(int first,int second)49     inline void set(int first, int second)
50     {
51         sides[Which].first = first;
52         sides[Which].second = second;
53     }
54 
55     template <int Which, int Index>
correct_to_zero()56     inline void correct_to_zero()
57     {
58         if (Index == 0)
59         {
60             sides[Which].first = 0;
61         }
62         else
63         {
64             sides[Which].second = 0;
65         }
66     }
67 
68     template <int Which, int Index>
get() const69     inline int get() const
70     {
71         return Index == 0 ? sides[Which].first : sides[Which].second;
72     }
73 
74 
75     // Returns true if both lying on the same side WRT the other
76     // (so either 1,1 or -1-1)
77     template <int Which>
same() const78     inline bool same() const
79     {
80         return sides[Which].first * sides[Which].second == 1;
81     }
82 
collinear() const83     inline bool collinear() const
84     {
85         return sides[0].first == 0
86             && sides[0].second == 0
87             && sides[1].first == 0
88             && sides[1].second == 0;
89     }
90 
crossing() const91     inline bool crossing() const
92     {
93         return sides[0].first * sides[0].second == -1
94             && sides[1].first * sides[1].second == -1;
95     }
96 
touching() const97     inline bool touching() const
98     {
99         return (sides[0].first * sides[1].first == -1
100             && sides[0].second == 0 && sides[1].second == 0)
101             || (sides[1].first * sides[0].first == -1
102             && sides[1].second == 0 && sides[0].second == 0);
103     }
104 
105     template <int Which>
one_touching() const106     inline bool one_touching() const
107     {
108         // This is normally a situation which can't occur:
109         // If one is completely left or right, the other cannot touch
110         return one_zero<Which>()
111             && sides[1 - Which].first * sides[1 - Which].second == 1;
112     }
113 
meeting() const114     inline bool meeting() const
115     {
116         // Two of them (in each segment) zero, two not
117         return one_zero<0>() && one_zero<1>();
118     }
119 
120     template <int Which>
zero() const121     inline bool zero() const
122     {
123         return sides[Which].first == 0 && sides[Which].second == 0;
124     }
125 
126     template <int Which>
one_zero() const127     inline bool one_zero() const
128     {
129         return (sides[Which].first == 0 && sides[Which].second != 0)
130             || (sides[Which].first != 0 && sides[Which].second == 0);
131     }
132 
one_of_all_zero() const133     inline bool one_of_all_zero() const
134     {
135         int const sum = std::abs(sides[0].first)
136                 + std::abs(sides[0].second)
137                 + std::abs(sides[1].first)
138                 + std::abs(sides[1].second);
139         return sum == 3;
140     }
141 
142 
143     template <int Which>
zero_index() const144     inline int zero_index() const
145     {
146         return sides[Which].first == 0 ? 0 : 1;
147     }
148 
149 #if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_DEBUG_ROBUSTNESS)
debug() const150     inline void debug() const
151     {
152         std::cout << sides[0].first << " "
153             << sides[0].second << " "
154             << sides[1].first << " "
155             << sides[1].second
156             << std::endl;
157     }
158 #endif
159 
reverse()160     inline void reverse()
161     {
162         std::swap(sides[0], sides[1]);
163     }
164 
165 //private :
166     std::pair<int, int> sides[2];
167 
168 };
169 
170 #if defined(_MSC_VER)
171 #pragma warning(pop)
172 #endif
173 
174 }} // namespace boost::geometry
175 
176 
177 #endif // BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
178