Skip to content

Commit 61ede09

Browse files
authored
Merge pull request #694 from Maxxen/v1.4-andium-dev
Setup CI for v1.4 branch, fix bug in st_distance when processing zero-length segments in polygon rings
2 parents 89c3e25 + 456d9f9 commit 61ede09

File tree

4 files changed

+50
-5
lines changed

4 files changed

+50
-5
lines changed

.github/workflows/MainDistributionPipeline.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ name: Main Extension Distribution Pipeline
55
on:
66
pull_request:
77
branches:
8-
- main
8+
- v1.4-andium
99
paths-ignore:
1010
- '**/README.md'
1111
- 'doc/**'
1212
push:
1313
branches:
14-
- main
14+
- v1.4-andium
1515
paths-ignore:
1616
- '**/README.md'
1717
- 'doc/**'
@@ -27,7 +27,7 @@ jobs:
2727
name: Build extension binaries
2828
uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@main
2929
with:
30-
duckdb_version: main
30+
duckdb_version: v1.4.1
3131
extension_name: spatial
3232
ci_tools_version: main
3333
vcpkg_commit: ce613c41372b23b1f51333815feb3edd87ef8a8b
@@ -38,7 +38,7 @@ jobs:
3838
uses: duckdb/extension-ci-tools/.github/workflows/_extension_deploy.yml@main
3939
secrets: inherit
4040
with:
41-
duckdb_version: main
41+
duckdb_version: v1.4.1
4242
ci_tools_version: main
4343
extension_name: spatial
4444
deploy_latest: ${{ startsWith(github.ref, 'refs/heads/v') || github.ref == 'refs/heads/main' }}

duckdb

Submodule duckdb updated 470 files

src/sgl/sgl.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,13 +3130,30 @@ static double point_segment_dist_sq(const vertex_xy &p, const vertex_xy &a, cons
31303130
return diff.norm_sq();
31313131
}
31323132

3133+
// Check if point P is on segment QR
31333134
static bool point_on_segment(const vertex_xy &p, const vertex_xy &q, const vertex_xy &r) {
31343135
return q.x >= std::min(p.x, r.x) && q.x <= std::max(p.x, r.x) && q.y >= std::min(p.y, r.y) &&
31353136
q.y <= std::max(p.y, r.y);
31363137
}
31373138

31383139
static bool segment_intersects(const vertex_xy &a1, const vertex_xy &a2, const vertex_xy &b1, const vertex_xy &b2) {
31393140
// Check if two segments intersect using the orientation method
3141+
// Handle degenerate cases where a segment is actually a single point
3142+
const bool a_is_point = (a1.x == a2.x && a1.y == a2.y);
3143+
const bool b_is_point = (b1.x == b2.x && b1.y == b2.y);
3144+
3145+
if (a_is_point && b_is_point) {
3146+
// Both are points: intersect only if identical
3147+
return (a1.x == b1.x && a1.y == b1.y);
3148+
}
3149+
if (a_is_point) {
3150+
// A is a point: check if A lies on segment B
3151+
return point_on_segment(a1, b1, b2);
3152+
}
3153+
if (b_is_point) {
3154+
// B is a point: check if B lies on segment A
3155+
return point_on_segment(b1, a1, a2);
3156+
}
31403157

31413158
const auto o1 = orient2d_fast(a1, a2, b1);
31423159
const auto o2 = orient2d_fast(a1, a2, b2);
@@ -3250,6 +3267,15 @@ static bool try_get_prepared_distance_lines(const prepared_geometry &lhs, const
32503267
for (uint32_t i = lhs_beg_idx + 1; i < lhs_end_idx; i++) {
32513268
memcpy(&lhs_next, lhs_vertex_array + i * lhs_vertex_width, sizeof(vertex_xy));
32523269

3270+
// If this is a zero-length segment, skip it
3271+
// LINESTRINGs must have at least two distinct vertices to be valid, so this is safe. Even if we skip
3272+
// this vertex now, we must eventually reach a non-zero-length segment that includes this vertex as
3273+
// its start point. It will therefore still contribute to the distance calculation once we process that
3274+
// segment.
3275+
if (lhs_prev.x == lhs_next.x && lhs_prev.y == lhs_next.y) {
3276+
continue;
3277+
}
3278+
32533279
// Quick check: If the distance between the segment and the box (all the segments)
32543280
// is greater than min_dist, we can skip the exact distance check
32553281

@@ -3268,6 +3294,13 @@ static bool try_get_prepared_distance_lines(const prepared_geometry &lhs, const
32683294
for (uint32_t j = rhs_beg_idx + 1; j < rhs_end_idx; j++) {
32693295
memcpy(&rhs_next, rhs_vertex_array + j * rhs_vertex_width, sizeof(vertex_xy));
32703296

3297+
// If this is a zero-length segment, skip it
3298+
// LINESTRINGs must have at least two distinct points to be valid, so this is safe.
3299+
// (see comment above)
3300+
if (rhs_prev.x == rhs_next.x && rhs_prev.y == rhs_next.y) {
3301+
continue;
3302+
}
3303+
32713304
// Quick check: If the distance between the segment bounds are greater than min_dist,
32723305
// we can skip the exact distance check
32733306
extent_xy rhs_seg;

test/sql/geometry/st_distance.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,15 @@ SELECT ST_Distance(
2626
----
2727
5
2828

29+
30+
# This test also comes from a bug report, where ST_Distance would incorrectly handle line segments with zero length.
31+
# The issue is that we were not properly considering segments where both endpoints are the same point, and conclude
32+
# that a zero length segment always intersects with any other segment, which is not correct. We now skip zero-length
33+
# segments when performing intersection tests between indexed polygon rings, and also handle zero-length segments as
34+
# points when performing regular segment-segment intersection tests.
35+
36+
query I
37+
select st_distance('POLYGON((0 0, 1 1, 1 1, 10 10, 0 0))'::GEOMETRY, 'POLYGON((4 0, 4 1, 5 1, 5 0, 4 0))'::GEOMETRY) != 0;
38+
----
39+
true
40+

0 commit comments

Comments
 (0)