File indexing completed on 2025-01-18 09:36:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP
0017 #define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP
0018
0019
0020 #include <boost/geometry/core/access.hpp>
0021 #include <boost/geometry/core/point_order.hpp>
0022 #include <boost/geometry/util/math.hpp>
0023 #include <boost/geometry/util/select_calculation_type.hpp>
0024
0025 #include <boost/geometry/strategies/side.hpp>
0026 #include <boost/geometry/strategies/within.hpp>
0027
0028
0029 namespace boost { namespace geometry
0030 {
0031
0032 namespace strategy { namespace within
0033 {
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 template
0052 <
0053 bool Reverse,
0054 typename Point,
0055 typename PointOfSegment = Point,
0056 typename CalculationType = void
0057 >
0058 class oriented_winding
0059 {
0060 typedef typename select_calculation_type
0061 <
0062 Point,
0063 PointOfSegment,
0064 CalculationType
0065 >::type calculation_type;
0066
0067
0068 typedef typename strategy::side::services::default_strategy
0069 <
0070 typename cs_tag<Point>::type
0071 >::type strategy_side_type;
0072
0073
0074
0075 class counter
0076 {
0077 int m_count;
0078 bool m_touches;
0079 calculation_type m_sum_area;
0080
0081 inline int code() const
0082 {
0083 return m_touches ? 0 : m_count == 0 ? -1 : 1;
0084 }
0085 inline int clockwise_oriented_code() const
0086 {
0087 return (m_sum_area > 0) ? code() : -code();
0088 }
0089 inline int oriented_code() const
0090 {
0091 return Reverse
0092 ? -clockwise_oriented_code()
0093 : clockwise_oriented_code();
0094 }
0095
0096 public :
0097 friend class oriented_winding;
0098
0099 inline counter()
0100 : m_count(0)
0101 , m_touches(false)
0102 , m_sum_area(0)
0103 {}
0104
0105 inline void add_to_area(calculation_type triangle)
0106 {
0107 m_sum_area += triangle;
0108 }
0109
0110 };
0111
0112
0113 template <size_t D>
0114 static inline int check_touch(Point const& point,
0115 PointOfSegment const& seg1, PointOfSegment const& seg2,
0116 counter& state)
0117 {
0118 calculation_type const p = get<D>(point);
0119 calculation_type const s1 = get<D>(seg1);
0120 calculation_type const s2 = get<D>(seg2);
0121 if ((s1 <= p && s2 >= p) || (s2 <= p && s1 >= p))
0122 {
0123 state.m_touches = true;
0124 }
0125 return 0;
0126 }
0127
0128
0129 template <size_t D>
0130 static inline int check_segment(Point const& point,
0131 PointOfSegment const& seg1, PointOfSegment const& seg2,
0132 counter& state)
0133 {
0134 calculation_type const p = get<D>(point);
0135 calculation_type const s1 = get<D>(seg1);
0136 calculation_type const s2 = get<D>(seg2);
0137
0138
0139
0140 bool eq1 = math::equals(s1, p);
0141 bool eq2 = math::equals(s2, p);
0142
0143 if (eq1 && eq2)
0144 {
0145
0146
0147 return check_touch<1 - D>(point, seg1, seg2, state);
0148 }
0149
0150 return
0151 eq1 ? (s2 > p ? 1 : -1)
0152 : eq2 ? (s1 > p ? -1 : 1)
0153 : s1 < p && s2 > p ? 2
0154 : s2 < p && s1 > p ? -2
0155 : 0;
0156 }
0157
0158
0159
0160
0161 public :
0162
0163
0164 typedef Point point_type;
0165 typedef PointOfSegment segment_point_type;
0166 typedef counter state_type;
0167
0168 static inline bool apply(Point const& point,
0169 PointOfSegment const& s1, PointOfSegment const& s2,
0170 counter& state)
0171 {
0172 state.add_to_area(get<0>(s2) * get<1>(s1) - get<0>(s1) * get<1>(s2));
0173
0174 int count = check_segment<1>(point, s1, s2, state);
0175 if (count != 0)
0176 {
0177 int side = strategy_side_type::apply(s1, s2, point);
0178 if (side == 0)
0179 {
0180
0181 state.m_touches = true;
0182 state.m_count = 0;
0183 return false;
0184 }
0185
0186
0187
0188
0189
0190 if (side * count > 0)
0191 {
0192 state.m_count += count;
0193 }
0194 }
0195 return ! state.m_touches;
0196 }
0197
0198 static inline int result(counter const& state)
0199 {
0200 return state.oriented_code();
0201 }
0202 };
0203
0204
0205 }}
0206
0207
0208 }}
0209
0210
0211 #endif