diff --git a/geo/src/algorithm/contains/mod.rs b/geo/src/algorithm/contains/mod.rs index 737996187..55c2bd952 100644 --- a/geo/src/algorithm/contains/mod.rs +++ b/geo/src/algorithm/contains/mod.rs @@ -184,6 +184,31 @@ mod test { assert!(poly.contains(&Point::new(1., 1.))); } #[test] + fn point_in_polygon_with_ray_passing_through_a_vertex_test() { + let linestring = LineString::from(vec![ + (1., 0.), + (0., 1.), + (-1., 0.), + (0., -1.), + ]); + let poly = Polygon::new(linestring, Vec::new()); + assert!(poly.contains(&Point::new(0., 0.))); + } + #[test] + fn point_in_polygon_with_ray_passing_through_a_vertex_and_not_crossing() { + let linestring = LineString::from(vec![ + (0., 0.), + (2., 0.), + (3., 1.), + (4., 0.), + (4., 2.), + (0., 2.), + (0., 0.), + ]); + let poly = Polygon::new(linestring, Vec::new()); + assert!(poly.contains(&Point::new(1., 1.))); + } + #[test] fn point_out_polygon_test() { let linestring = LineString::from(vec![(0., 0.), (2., 0.), (2., 2.), (0., 2.), (0., 0.)]); let poly = Polygon::new(linestring, Vec::new()); diff --git a/geo/src/utils.rs b/geo/src/utils.rs index 0b78245ca..3b46185f4 100644 --- a/geo/src/utils.rs +++ b/geo/src/utils.rs @@ -140,10 +140,19 @@ where } // Ignore if the intersection of the line is - // possibly at the beginning of the line. This is to + // possibly at the beginning/end of the line, and + // the line lies below the ray. This is to // prevent a double counting when the ray passes - // through a vertex of the plygon - if line.start.y == coord.y { + // through a vertex of the polygon. + // + // The below logic handles two cases: + // 1. if the ray enters/exits the polygon + // at the point of intersection + // 2. if the ray touches a vertex, + // but doesn't enter/exit at that point + if (line.start.y == coord.y && line.end.y < coord.y) + || (line.end.y == coord.y && line.start.y < coord.y) + { continue; }