Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
de9a55a
feat: implement ST_Expand
bradh Aug 30, 2025
ca2d45d
fix typo in variable name
bradh Aug 31, 2025
43b38f2
Fix typo
szarnyasg Sep 25, 2025
e32e07e
update CI
Maxxen Oct 24, 2025
456d9f9
pin to duckdb v1.4.1, fix bug in st_distance when processing zero-len…
Maxxen Oct 24, 2025
61ede09
Merge pull request #694 from Maxxen/v1.4-andium-dev
Maxxen Oct 24, 2025
2902050
well. we're stuck on arrow extensions for now since gdal emits/output…
Maxxen Oct 24, 2025
9e072dc
nvm figured out how to force geoarrow.wkb
Maxxen Oct 24, 2025
be6a721
Merge branch 'v1.4-andium' of https://github.com/duckdb/duckdb-spatia…
Maxxen Oct 31, 2025
3456f18
fix: Linestring corrupt PBF issue
ilyabo Oct 28, 2025
b56d9ce
fix tests
ilyabo Oct 29, 2025
a78bfe4
fix invalid geometries in ST_AsMVTGeom
Jesperpaulsen Oct 23, 2025
9d98258
format, always orient MVT geom after processing
Maxxen Oct 31, 2025
c10ae36
fix typo
Maxxen Oct 31, 2025
0740b2b
Merge remote-tracking branch 'bradh/fraction_typo_2025-08-31' into v1…
Maxxen Oct 31, 2025
6127c4f
Merge remote-tracking branch 'upstream/typo2' into v1.4-andium-dev
Maxxen Oct 31, 2025
af00774
fix 2D_FromWKB functions
Maxxen Oct 31, 2025
72cc0b6
Merge remote-tracking branch 'bradh/st_extend_2025-08-31' into v1.4-a…
Maxxen Oct 31, 2025
25838f3
fix reused rtree nodes not being zeroed
Maxxen Oct 31, 2025
7d2a97d
update to duckdb v1.5, apply patches
Maxxen Nov 11, 2025
273b1a2
use duckdb native geometry type instead
Maxxen Nov 11, 2025
0772499
adjust serialization, cleanup old code
Maxxen Nov 12, 2025
f7d91ca
remove more code
Maxxen Nov 13, 2025
0260f6b
Merge branch 'gdal-arrow' into neo-geo
Maxxen Nov 13, 2025
c3ab04c
begin sketching out new gdal
Maxxen Nov 13, 2025
5cef454
pass on stats and cardinality
Maxxen Nov 14, 2025
a6b8cf0
filter pushdown
Maxxen Nov 14, 2025
b7e375f
fixup osm
Maxxen Nov 14, 2025
68e3651
adjust gdal errors
Maxxen Nov 14, 2025
737763e
fix bounds check in osm reader
Maxxen Nov 14, 2025
9fdcf9f
move filesystem
Maxxen Nov 18, 2025
c1f6acd
dont remote cache
Maxxen Nov 18, 2025
0dd525d
move back into gdal_module
Maxxen Nov 18, 2025
c4a1ea6
cleanup
Maxxen Nov 18, 2025
5ef8499
write ogc_fid if present
Maxxen Nov 19, 2025
3fb89eb
update mvt to use wkb format
Maxxen Nov 19, 2025
2db44b0
sketch out wkb module
Maxxen Nov 19, 2025
87bfbb9
add implicit cast from old-style geometry
Maxxen Nov 19, 2025
7ed242d
adjust test
Maxxen Nov 19, 2025
4cc03bc
update to main duckdb
Maxxen Nov 20, 2025
ffa88a3
forgot CI
Maxxen Nov 20, 2025
78b6217
fix override
Maxxen Nov 20, 2025
daafd7d
fix bug in TryGetCachedBounds, add optimizer path for more spatial (i…
Maxxen Nov 20, 2025
f691040
format
Maxxen Nov 20, 2025
9155110
use arena for geos deserialization
Maxxen Nov 21, 2025
3868eed
tweak spatial join
Maxxen Nov 21, 2025
bd169da
actually prepare deserialization
Maxxen Nov 21, 2025
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
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Set extension name here
set(TARGET_NAME spatial)
set(EXTENSION_NAME ${TARGET_NAME}_extension)
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard")
set(CMAKE_CXX_STANDARD
11
CACHE STRING "C++ standard")

if(EMSCRIPTEN)
# _LINKED_LIBS influences only Wasm compilation it's unclear why this is
Expand Down
10 changes: 0 additions & 10 deletions dist_join.sql

This file was deleted.

2 changes: 1 addition & 1 deletion duckdb
Submodule duckdb updated 2928 files
113 changes: 113 additions & 0 deletions src/sgl/sgl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2382,6 +2382,86 @@ bool ops::get_euclidean_distance(const geometry &lhs_geom, const geometry &rhs_g
return found;
}

// Visit all non-collection geometries
template <class CALLBACK>
void visit_leaf_pairs(const geometry &lhs, const geometry &rhs, CALLBACK &&callback) {
const auto lhs_root = lhs.get_parent();
auto lhs_part = &lhs;

while (true) {
switch (lhs_part->get_type()) {
case geometry_type::POINT:
case geometry_type::LINESTRING:
case geometry_type::POLYGON: {

const auto rhs_root = rhs.get_parent();
auto rhs_part = &rhs;

while (true) {
switch (rhs_part->get_type()) {
case geometry_type::POINT:
case geometry_type::LINESTRING:
case geometry_type::POLYGON: {
// Found a pair of leaf geometries
// If the callback returns true, we stop visiting
if (callback(*lhs_part, *rhs_part)) {
return;
}
} break;
case geometry_type::MULTI_POINT:
case geometry_type::MULTI_LINESTRING:
case geometry_type::MULTI_POLYGON:
case geometry_type::GEOMETRY_COLLECTION:
if (rhs_part->is_empty()) {
break;
}
rhs_part = rhs_part->get_first_part();
continue;
default:
break;
}

while (true) {
const auto parent = rhs_part->get_parent();
if (parent == rhs_root) {
break;
}
if (rhs_part != parent->get_last_part()) {
rhs_part = rhs_part->get_next();
break;
}
rhs_part = parent;
}
}

} break;
case geometry_type::MULTI_POINT:
case geometry_type::MULTI_LINESTRING:
case geometry_type::MULTI_POLYGON:
case geometry_type::GEOMETRY_COLLECTION:
if (lhs_part->is_empty()) {
break;
}
lhs_part = lhs_part->get_first_part();
continue;
default:
break;
}

while (true) {
const auto parent = lhs_part->get_parent();
if (parent == lhs_root) {
return;
}
if (lhs_part != parent->get_last_part()) {
lhs_part = lhs_part->get_next();
break;
}
lhs_part = parent;
}
}
}

} // namespace sgl

//======================================================================================================================
Expand Down Expand Up @@ -3130,13 +3210,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 +3347,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 +3374,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
4 changes: 4 additions & 0 deletions src/sgl/sgl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ struct vertex_xyzm {
return dummy;
}
}

bool all_nan() const {
return std::isnan(x) && std::isnan(y) && std::isnan(z) && std::isnan(m);
}
};

} // namespace sgl
Expand Down
6 changes: 2 additions & 4 deletions src/spatial/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ add_subdirectory(index)
add_subdirectory(operators)

set(EXTENSION_SOURCES
${EXTENSION_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/spatial_extension.cpp
${EXTENSION_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/spatial_extension.cpp
${CMAKE_CURRENT_SOURCE_DIR}/spatial_types.cpp
${CMAKE_CURRENT_SOURCE_DIR}/spatial_geoarrow.cpp
PARENT_SCOPE)
PARENT_SCOPE)
7 changes: 2 additions & 5 deletions src/spatial/geometry/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
set(EXTENSION_SOURCES
${EXTENSION_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/geometry_processor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/wkb_writer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/geometry_serialization.cpp
PARENT_SCOPE)
${EXTENSION_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/geometry_serialization.cpp
PARENT_SCOPE)
7 changes: 0 additions & 7 deletions src/spatial/geometry/geometry_processor.cpp

This file was deleted.

Loading
Loading