diff --git a/src/sgl/sgl.cpp b/src/sgl/sgl.cpp index c48388a7..b45b857b 100644 --- a/src/sgl/sgl.cpp +++ b/src/sgl/sgl.cpp @@ -2369,7 +2369,9 @@ point_in_polygon_result prepared_geometry::contains(const vertex_xy &vert) const // Now, we are at a leaf, so we need to check the segments const auto beg_idx = entry * NODE_SIZE; - const auto end_idx = math::min(beg_idx + NODE_SIZE, index.items_count); + // We +1 to the node size here to get the end index, because the last segment spans across + // the end of the node. And our indexes are always sequential. + const auto end_idx = math::min(beg_idx + NODE_SIZE + 1, index.items_count); // Loop over the segments vertex_xy prev; @@ -2436,7 +2438,9 @@ bool prepared_geometry::try_get_distance_recursive(uint32_t level, uint32_t entr const auto vertex_width = get_vertex_width(); const auto beg_idx = entry * NODE_SIZE; - const auto end_idx = math::min(beg_idx + NODE_SIZE, index.items_count); + // We +1 to the node size here to get the end index, because the last segment spans across + // the end of the node. And our indexes are always sequential. + const auto end_idx = math::min(beg_idx + NODE_SIZE + 1, index.items_count); if (beg_idx >= end_idx) { return false; // No segments to check diff --git a/test/sql/geometry/st_distance.test b/test/sql/geometry/st_distance.test new file mode 100644 index 00000000..226848a3 --- /dev/null +++ b/test/sql/geometry/st_distance.test @@ -0,0 +1,25 @@ +require spatial + +# This test case comes from a bug report, where the indexed point-in-polygon check would not consider that +# the second vertex of the last segment in each index node neccessarily have to be the first vertex of the next segment. +# Therefore when performing a raycast from a point to a polygon where the ray would intersect +# the segment formed by the last vertex in a index leaf node, and the first vertex in the next segment, the result +# would be incorrect. +# To test this, we create a polygon with 40 vertices, causing two index leaf nodes (0-31, 33-40) to be created when +# preparing the polygon, and we then query a point that is to the left of the polygon, but right between the segment +# spanning the two nodes (31-32). + +query I +SELECT ST_Distance( + ST_Point(-5, 31), + -- 32 points + ST_GeomFromText('POLYGON(( + 0 0, 0 1, 0 2, 0 3, 0 4, 0 5, 0 6, 0 7, + 0 8, 0 9, 0 10, 0 11, 0 12, 0 13, 0 14, 0 15, + 0 16, 0 17, 0 18, 0 19, 0 20, 0 21, 0 22, 0 23, + 0 24, 0 25, 0 26, 0 27, 0 28, 0 29, 0 30, 0 31, + 0 32, 0 33, 0 34, 0 35, 0 36, 0 37, 0 38, 0 39, + 0 0))')); +---- +5 +