Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/MainDistributionPipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ name: Main Extension Distribution Pipeline
on:
pull_request:
branches:
- main
- v1.4-andium
paths-ignore:
- '**/README.md'
- 'doc/**'
push:
branches:
- main
- v1.4-andium
paths-ignore:
- '**/README.md'
- 'doc/**'
Expand All @@ -27,7 +27,7 @@ jobs:
name: Build extension binaries
uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@main
with:
duckdb_version: main
duckdb_version: v1.4.1
extension_name: spatial
ci_tools_version: main
vcpkg_commit: ce613c41372b23b1f51333815feb3edd87ef8a8b
Expand All @@ -38,7 +38,7 @@ jobs:
uses: duckdb/extension-ci-tools/.github/workflows/_extension_deploy.yml@main
secrets: inherit
with:
duckdb_version: main
duckdb_version: v1.4.1
ci_tools_version: main
extension_name: spatial
deploy_latest: ${{ startsWith(github.ref, 'refs/heads/v') || github.ref == 'refs/heads/main' }}
2 changes: 1 addition & 1 deletion duckdb
Submodule duckdb updated 470 files
33 changes: 33 additions & 0 deletions src/sgl/sgl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3130,13 +3130,30 @@ static double point_segment_dist_sq(const vertex_xy &p, const vertex_xy &a, cons
return diff.norm_sq();
}

// Check if point P is on segment QR
static bool point_on_segment(const vertex_xy &p, const vertex_xy &q, const vertex_xy &r) {
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) &&
q.y <= std::max(p.y, r.y);
}

static bool segment_intersects(const vertex_xy &a1, const vertex_xy &a2, const vertex_xy &b1, const vertex_xy &b2) {
// Check if two segments intersect using the orientation method
// Handle degenerate cases where a segment is actually a single point
const bool a_is_point = (a1.x == a2.x && a1.y == a2.y);
const bool b_is_point = (b1.x == b2.x && b1.y == b2.y);

if (a_is_point && b_is_point) {
// Both are points: intersect only if identical
return (a1.x == b1.x && a1.y == b1.y);
}
if (a_is_point) {
// A is a point: check if A lies on segment B
return point_on_segment(a1, b1, b2);
}
if (b_is_point) {
// B is a point: check if B lies on segment A
return point_on_segment(b1, a1, a2);
}

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

// If this is a zero-length segment, skip it
// LINESTRINGs must have at least two distinct vertices to be valid, so this is safe. Even if we skip
// this vertex now, we must eventually reach a non-zero-length segment that includes this vertex as
// its start point. It will therefore still contribute to the distance calculation once we process that
// segment.
if (lhs_prev.x == lhs_next.x && lhs_prev.y == lhs_next.y) {
continue;
}

// Quick check: If the distance between the segment and the box (all the segments)
// is greater than min_dist, we can skip the exact distance check

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

// If this is a zero-length segment, skip it
// LINESTRINGs must have at least two distinct points to be valid, so this is safe.
// (see comment above)
if (rhs_prev.x == rhs_next.x && rhs_prev.y == rhs_next.y) {
continue;
}

// Quick check: If the distance between the segment bounds are greater than min_dist,
// we can skip the exact distance check
extent_xy rhs_seg;
Expand Down
12 changes: 12 additions & 0 deletions test/sql/geometry/st_distance.test
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,15 @@ SELECT ST_Distance(
----
5


# This test also comes from a bug report, where ST_Distance would incorrectly handle line segments with zero length.
# The issue is that we were not properly considering segments where both endpoints are the same point, and conclude
# that a zero length segment always intersects with any other segment, which is not correct. We now skip zero-length
# segments when performing intersection tests between indexed polygon rings, and also handle zero-length segments as
# points when performing regular segment-segment intersection tests.

query I
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;
----
true

Loading