Skip to content

Commit 44ed800

Browse files
authored
Merge pull request #713 from Maxxen/neo-geo
2 parents 89c3e25 + bd169da commit 44ed800

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3225
-4386
lines changed

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
44
# Set extension name here
55
set(TARGET_NAME spatial)
66
set(EXTENSION_NAME ${TARGET_NAME}_extension)
7-
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard")
7+
set(CMAKE_CXX_STANDARD
8+
11
9+
CACHE STRING "C++ standard")
810

911
if(EMSCRIPTEN)
1012
# _LINKED_LIBS influences only Wasm compilation it's unclear why this is

dist_join.sql

Lines changed: 0 additions & 10 deletions
This file was deleted.

duckdb

Submodule duckdb updated 2928 files

src/sgl/sgl.cpp

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2382,6 +2382,86 @@ bool ops::get_euclidean_distance(const geometry &lhs_geom, const geometry &rhs_g
23822382
return found;
23832383
}
23842384

2385+
// Visit all non-collection geometries
2386+
template <class CALLBACK>
2387+
void visit_leaf_pairs(const geometry &lhs, const geometry &rhs, CALLBACK &&callback) {
2388+
const auto lhs_root = lhs.get_parent();
2389+
auto lhs_part = &lhs;
2390+
2391+
while (true) {
2392+
switch (lhs_part->get_type()) {
2393+
case geometry_type::POINT:
2394+
case geometry_type::LINESTRING:
2395+
case geometry_type::POLYGON: {
2396+
2397+
const auto rhs_root = rhs.get_parent();
2398+
auto rhs_part = &rhs;
2399+
2400+
while (true) {
2401+
switch (rhs_part->get_type()) {
2402+
case geometry_type::POINT:
2403+
case geometry_type::LINESTRING:
2404+
case geometry_type::POLYGON: {
2405+
// Found a pair of leaf geometries
2406+
// If the callback returns true, we stop visiting
2407+
if (callback(*lhs_part, *rhs_part)) {
2408+
return;
2409+
}
2410+
} break;
2411+
case geometry_type::MULTI_POINT:
2412+
case geometry_type::MULTI_LINESTRING:
2413+
case geometry_type::MULTI_POLYGON:
2414+
case geometry_type::GEOMETRY_COLLECTION:
2415+
if (rhs_part->is_empty()) {
2416+
break;
2417+
}
2418+
rhs_part = rhs_part->get_first_part();
2419+
continue;
2420+
default:
2421+
break;
2422+
}
2423+
2424+
while (true) {
2425+
const auto parent = rhs_part->get_parent();
2426+
if (parent == rhs_root) {
2427+
break;
2428+
}
2429+
if (rhs_part != parent->get_last_part()) {
2430+
rhs_part = rhs_part->get_next();
2431+
break;
2432+
}
2433+
rhs_part = parent;
2434+
}
2435+
}
2436+
2437+
} break;
2438+
case geometry_type::MULTI_POINT:
2439+
case geometry_type::MULTI_LINESTRING:
2440+
case geometry_type::MULTI_POLYGON:
2441+
case geometry_type::GEOMETRY_COLLECTION:
2442+
if (lhs_part->is_empty()) {
2443+
break;
2444+
}
2445+
lhs_part = lhs_part->get_first_part();
2446+
continue;
2447+
default:
2448+
break;
2449+
}
2450+
2451+
while (true) {
2452+
const auto parent = lhs_part->get_parent();
2453+
if (parent == lhs_root) {
2454+
return;
2455+
}
2456+
if (lhs_part != parent->get_last_part()) {
2457+
lhs_part = lhs_part->get_next();
2458+
break;
2459+
}
2460+
lhs_part = parent;
2461+
}
2462+
}
2463+
}
2464+
23852465
} // namespace sgl
23862466

23872467
//======================================================================================================================
@@ -3130,13 +3210,30 @@ static double point_segment_dist_sq(const vertex_xy &p, const vertex_xy &a, cons
31303210
return diff.norm_sq();
31313211
}
31323212

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

31383219
static bool segment_intersects(const vertex_xy &a1, const vertex_xy &a2, const vertex_xy &b1, const vertex_xy &b2) {
31393220
// Check if two segments intersect using the orientation method
3221+
// Handle degenerate cases where a segment is actually a single point
3222+
const bool a_is_point = (a1.x == a2.x && a1.y == a2.y);
3223+
const bool b_is_point = (b1.x == b2.x && b1.y == b2.y);
3224+
3225+
if (a_is_point && b_is_point) {
3226+
// Both are points: intersect only if identical
3227+
return (a1.x == b1.x && a1.y == b1.y);
3228+
}
3229+
if (a_is_point) {
3230+
// A is a point: check if A lies on segment B
3231+
return point_on_segment(a1, b1, b2);
3232+
}
3233+
if (b_is_point) {
3234+
// B is a point: check if B lies on segment A
3235+
return point_on_segment(b1, a1, a2);
3236+
}
31403237

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

3350+
// If this is a zero-length segment, skip it
3351+
// LINESTRINGs must have at least two distinct vertices to be valid, so this is safe. Even if we skip
3352+
// this vertex now, we must eventually reach a non-zero-length segment that includes this vertex as
3353+
// its start point. It will therefore still contribute to the distance calculation once we process that
3354+
// segment.
3355+
if (lhs_prev.x == lhs_next.x && lhs_prev.y == lhs_next.y) {
3356+
continue;
3357+
}
3358+
32533359
// Quick check: If the distance between the segment and the box (all the segments)
32543360
// is greater than min_dist, we can skip the exact distance check
32553361

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

3377+
// If this is a zero-length segment, skip it
3378+
// LINESTRINGs must have at least two distinct points to be valid, so this is safe.
3379+
// (see comment above)
3380+
if (rhs_prev.x == rhs_next.x && rhs_prev.y == rhs_next.y) {
3381+
continue;
3382+
}
3383+
32713384
// Quick check: If the distance between the segment bounds are greater than min_dist,
32723385
// we can skip the exact distance check
32733386
extent_xy rhs_seg;

src/sgl/sgl.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ struct vertex_xyzm {
139139
return dummy;
140140
}
141141
}
142+
143+
bool all_nan() const {
144+
return std::isnan(x) && std::isnan(y) && std::isnan(z) && std::isnan(m);
145+
}
142146
};
143147

144148
} // namespace sgl

src/spatial/CMakeLists.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ add_subdirectory(index)
55
add_subdirectory(operators)
66

77
set(EXTENSION_SOURCES
8-
${EXTENSION_SOURCES}
9-
${CMAKE_CURRENT_SOURCE_DIR}/spatial_extension.cpp
8+
${EXTENSION_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/spatial_extension.cpp
109
${CMAKE_CURRENT_SOURCE_DIR}/spatial_types.cpp
11-
${CMAKE_CURRENT_SOURCE_DIR}/spatial_geoarrow.cpp
12-
PARENT_SCOPE)
10+
PARENT_SCOPE)
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
set(EXTENSION_SOURCES
2-
${EXTENSION_SOURCES}
3-
${CMAKE_CURRENT_SOURCE_DIR}/geometry_processor.cpp
4-
${CMAKE_CURRENT_SOURCE_DIR}/wkb_writer.cpp
5-
${CMAKE_CURRENT_SOURCE_DIR}/geometry_serialization.cpp
6-
PARENT_SCOPE)
2+
${EXTENSION_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/geometry_serialization.cpp
3+
PARENT_SCOPE)

src/spatial/geometry/geometry_processor.cpp

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)