From 3bdefedab16b180841ba5c4b32eaaa494f42d8c8 Mon Sep 17 00:00:00 2001
From: Andrii Sydorchuk <asydorchuk@spotify.com>
Date: Wed, 19 Mar 2014 21:10:09 +0100
Subject: [PATCH] Polygon: fixing reopend issue #6366: defect in polygon 90
contains.
---
include/boost/polygon/polygon_traits.hpp | 34 +++++++++++++++++++++++++-------
1 file changed, 27 insertions(+), 7 deletions(-)
diff --git a/include/boost/polygon/polygon_traits.hpp b/include/boost/polygon/polygon_traits.hpp
index 6055bc7..b03d00f 100644
a
|
b
|
namespace boost { namespace polygon{
|
1129 | 1129 | |
1130 | 1130 | template <typename T, typename input_point_type> |
1131 | 1131 | typename enable_if< |
1132 | | typename gtl_and< typename is_polygon_90_type<T>::type, |
1133 | | typename gtl_same_type<typename geometry_concept<input_point_type>::type, point_concept>::type>::type, |
1134 | | bool>::type |
1135 | | contains(const T& polygon, const input_point_type& point, bool consider_touch = true) { |
| 1132 | typename gtl_and< |
| 1133 | typename is_polygon_90_type<T>::type, |
| 1134 | typename gtl_same_type< |
| 1135 | typename geometry_concept<input_point_type>::type, |
| 1136 | point_concept |
| 1137 | >::type |
| 1138 | >::type, |
| 1139 | bool |
| 1140 | >::type contains( |
| 1141 | const T& polygon, |
| 1142 | const input_point_type& point, |
| 1143 | bool consider_touch = true) { |
1136 | 1144 | typedef T polygon_type; |
1137 | 1145 | typedef typename polygon_traits<polygon_type>::coordinate_type coordinate_type; |
1138 | 1146 | typedef typename polygon_traits<polygon_type>::iterator_type iterator; |
1139 | 1147 | typedef typename std::iterator_traits<iterator>::value_type point_type; |
1140 | 1148 | coordinate_type point_x = x(point); |
1141 | 1149 | coordinate_type point_y = y(point); |
1142 | | bool inside = false; |
| 1150 | // Check how many intersections has the ray extended from the given |
| 1151 | // point in the x-axis negative direction with the polygon edges. |
| 1152 | // If the number is odd the point is within the polygon, otherwise not. |
| 1153 | // We can safely ignore horizontal edges, however intersections with |
| 1154 | // end points of the vertical edges require special handling. We should |
| 1155 | // add one intersection in case horizontal edges that extend vertical edge |
| 1156 | // point in the same direction. |
| 1157 | int num_full_intersections = 0; |
| 1158 | int num_half_intersections = 0; |
1143 | 1159 | for (iterator iter = begin_points(polygon); iter != end_points(polygon);) { |
1144 | 1160 | point_type curr_point = *iter; |
1145 | 1161 | ++iter; |
… |
… |
namespace boost { namespace polygon{
|
1154 | 1170 | if (x(curr_point) == point_x) { |
1155 | 1171 | return consider_touch; |
1156 | 1172 | } |
1157 | | inside ^= true; |
| 1173 | ++num_full_intersections; |
| 1174 | } |
| 1175 | if (point_y == min_y || point_y == max_y) { |
| 1176 | num_half_intersections += (y(curr_point) < y(next_point) ? 1 : -1); |
1158 | 1177 | } |
1159 | 1178 | } else { |
1160 | 1179 | coordinate_type min_x = (std::min)(x(curr_point), x(next_point)); |
… |
… |
namespace boost { namespace polygon{
|
1166 | 1185 | } |
1167 | 1186 | } |
1168 | 1187 | } |
1169 | | return inside; |
| 1188 | int total_intersections = num_full_intersections + (num_half_intersections >> 1); |
| 1189 | return total_intersections & 1; |
1170 | 1190 | } |
1171 | 1191 | |
1172 | 1192 | //TODO: refactor to expose as user APIs |