Skip to content

Commit 8734819

Browse files
authored
Merge pull request #763 from Maxxen/v1.5-variegata-dev
2 parents 03611be + d3ac3cc commit 8734819

File tree

3 files changed

+153
-7
lines changed

3 files changed

+153
-7
lines changed

src/spatial/modules/proj/proj_module.cpp

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,22 @@ struct ST_Transform {
221221
auto &data = other.Cast<TypedBindData>();
222222
return normalize == data.normalize && source_crs == data.source_crs && target_crs == data.target_crs;
223223
}
224+
225+
static void Serialize(Serializer &serializer, const optional_ptr<FunctionData> bind_data_p,
226+
const ScalarFunction &function) {
227+
auto &bind_data = bind_data_p->Cast<TypedBindData>();
228+
serializer.WritePropertyWithDefault(100, "normalize", bind_data.normalize);
229+
serializer.WritePropertyWithDefault(101, "source", bind_data.source_crs);
230+
serializer.WritePropertyWithDefault(102, "target", bind_data.target_crs);
231+
}
232+
233+
static unique_ptr<FunctionData> Deserialize(Deserializer &deserializer, ScalarFunction &function) {
234+
auto result = make_uniq<TypedBindData>();
235+
deserializer.ReadPropertyWithDefault(100, "normalize", result->normalize);
236+
deserializer.ReadPropertyWithDefault(101, "source", result->source_crs);
237+
deserializer.ReadPropertyWithDefault(102, "target", result->target_crs);
238+
return std::move(result);
239+
}
224240
};
225241

226242
static unique_ptr<FunctionData> BindTyped(ClientContext &ctx, ScalarFunction &func,
@@ -309,6 +325,7 @@ struct ST_Transform {
309325
return std::move(result);
310326
}
311327

328+
312329
//------------------------------------------------------------------------------------------------------------------
313330
// Local State
314331
//------------------------------------------------------------------------------------------------------------------
@@ -655,6 +672,8 @@ struct ST_Transform {
655672

656673
variant.SetInit(LocalState::Init);
657674
variant.SetBind(BindTyped);
675+
variant.SetSerialize(TypedBindData::Serialize);
676+
variant.SetDeserialize(TypedBindData::Deserialize);
658677
variant.SetFunction(ExecuteGeometryTyped);
659678
variant.CanThrowErrors();
660679
});
@@ -667,6 +686,8 @@ struct ST_Transform {
667686

668687
variant.SetInit(LocalState::Init);
669688
variant.SetBind(BindTyped);
689+
variant.SetSerialize(TypedBindData::Serialize);
690+
variant.SetDeserialize(TypedBindData::Deserialize);
670691
variant.SetFunction(ExecuteGeometryTyped);
671692
variant.CanThrowErrors();
672693
});
@@ -1389,13 +1410,25 @@ struct ST_DWithin_Spheroid {
13891410
geod_geodesic geod = {};
13901411
geod_init(&geod, EARTH_A, EARTH_F);
13911412

1392-
GenericExecutor::ExecuteTernary<POINT_TYPE, POINT_TYPE, DISTANCE_TYPE, BOOL_TYPE>(
1393-
args.data[0], args.data[1], args.data[2], result, args.size(),
1394-
[&](const POINT_TYPE &p1, const POINT_TYPE &p2, const DISTANCE_TYPE &limit) {
1395-
double distance;
1396-
geod_inverse(&geod, p1.a_val, p1.b_val, p2.a_val, p2.b_val, &distance, nullptr, nullptr);
1397-
return distance <= limit.val;
1398-
});
1413+
const auto &bdata = state.expr.Cast<BoundFunctionExpression>().bind_info->Cast<GeodesicBindData>();
1414+
1415+
if (bdata.always_xy) {
1416+
GenericExecutor::ExecuteTernary<POINT_TYPE, POINT_TYPE, DISTANCE_TYPE, BOOL_TYPE>(
1417+
args.data[0], args.data[1], args.data[2], result, args.size(),
1418+
[&](const POINT_TYPE &p1, const POINT_TYPE &p2, const DISTANCE_TYPE &limit) {
1419+
double distance;
1420+
geod_inverse(&geod, p1.b_val, p1.a_val, p2.b_val, p2.a_val, &distance, nullptr, nullptr);
1421+
return distance <= limit.val;
1422+
});
1423+
} else {
1424+
GenericExecutor::ExecuteTernary<POINT_TYPE, POINT_TYPE, DISTANCE_TYPE, BOOL_TYPE>(
1425+
args.data[0], args.data[1], args.data[2], result, args.size(),
1426+
[&](const POINT_TYPE &p1, const POINT_TYPE &p2, const DISTANCE_TYPE &limit) {
1427+
double distance;
1428+
geod_inverse(&geod, p1.a_val, p1.b_val, p2.a_val, p2.b_val, &distance, nullptr, nullptr);
1429+
return distance <= limit.val;
1430+
});
1431+
}
13991432
}
14001433

14011434
static constexpr auto DESCRIPTION = R"(
@@ -1414,6 +1447,7 @@ struct ST_DWithin_Spheroid {
14141447
variant.AddParameter("p2", GeoTypes::POINT_2D());
14151448
variant.AddParameter("distance", LogicalType::DOUBLE);
14161449
variant.SetReturnType(LogicalType::BOOLEAN);
1450+
variant.SetBind(GeodesicBindData::Bind);
14171451

14181452
variant.SetFunction(Execute);
14191453
variant.CanThrowErrors();

src/spatial/util/function_builder.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class ScalarFunctionVariantBuilder {
5353
void SetFunction(scalar_function_t fn);
5454
void SetInit(init_local_state_t init);
5555
void SetBind(bind_scalar_function_t bind);
56+
void SetSerialize(function_serialize_t serialize);
57+
void SetDeserialize(function_deserialize_t deserialize);
5658
void SetDescription(const string &desc);
5759
void SetExample(const string &ex);
5860
void CanThrowErrors();
@@ -86,6 +88,12 @@ inline void ScalarFunctionVariantBuilder::SetInit(init_local_state_t init) {
8688
inline void ScalarFunctionVariantBuilder::SetBind(bind_scalar_function_t bind) {
8789
function.bind = bind;
8890
}
91+
inline void ScalarFunctionVariantBuilder::SetSerialize(function_serialize_t serialize) {
92+
function.serialize = serialize;
93+
}
94+
inline void ScalarFunctionVariantBuilder::SetDeserialize(function_deserialize_t deserialize) {
95+
function.deserialize = deserialize;
96+
}
8997

9098
inline void ScalarFunctionVariantBuilder::SetDescription(const string &desc) {
9199
description.description = desc;

test/sql/st_spheroid.test

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
require spatial
2+
3+
query I
4+
SELECT ST_DWithin_Spheroid(
5+
st_point(40.6446, -73.7797),
6+
st_point(52.3130, 4.7725),
7+
6000000.0
8+
);
9+
----
10+
true
11+
12+
# Points within 5000km should return false
13+
query I
14+
SELECT ST_DWithin_Spheroid(
15+
st_point(40.6446, -73.7797),
16+
st_point(52.3130, 4.7725),
17+
5000000.0
18+
);
19+
----
20+
false
21+
22+
# Same point should be within any positive distance
23+
query I
24+
SELECT ST_DWithin_Spheroid(
25+
st_point(40.6446, -73.7797),
26+
st_point(40.6446, -73.7797),
27+
0.0
28+
);
29+
----
30+
true
31+
32+
# Same point should be within distance 0
33+
query I
34+
SELECT ST_DWithin_Spheroid(
35+
st_point(0.0, 0.0),
36+
st_point(0.0, 0.0),
37+
0.0
38+
);
39+
----
40+
true
41+
42+
# Very close points within 1 meter
43+
query I
44+
SELECT ST_DWithin_Spheroid(
45+
st_point(52.373123, 4.892360),
46+
st_point(52.373124, 4.892361),
47+
1.0
48+
);
49+
----
50+
true
51+
52+
# Verify consistency with ST_Distance_Spheroid
53+
query I
54+
SELECT ST_DWithin_Spheroid(
55+
st_point(40.6446, -73.7797),
56+
st_point(52.3130, 4.7725),
57+
ST_Distance_Spheroid(
58+
st_point(40.6446, -73.7797),
59+
st_point(52.3130, 4.7725)
60+
)
61+
);
62+
----
63+
true
64+
65+
# Test with always_xy setting
66+
statement ok
67+
SET geometry_always_xy = true;
68+
69+
query I
70+
SELECT ST_DWithin_Spheroid(
71+
st_point(-73.7797, 40.6446),
72+
st_point(4.7725, 52.3130),
73+
6000000.0
74+
);
75+
----
76+
true
77+
78+
query I
79+
SELECT ST_DWithin_Spheroid(
80+
st_point(-73.7797, 40.6446),
81+
st_point(4.7725, 52.3130),
82+
5000000.0
83+
);
84+
----
85+
false
86+
87+
statement ok
88+
SET geometry_always_xy = false;
89+
90+
# Test with NULL inputs
91+
query I
92+
SELECT ST_DWithin_Spheroid(NULL::POINT_2D, st_point(52.3130, 4.7725), 6000000.0);
93+
----
94+
NULL
95+
96+
query I
97+
SELECT ST_DWithin_Spheroid(st_point(40.6446, -73.7797), NULL::POINT_2D, 6000000.0);
98+
----
99+
NULL
100+
101+
query I
102+
SELECT ST_DWithin_Spheroid(st_point(40.6446, -73.7797), st_point(52.3130, 4.7725), NULL);
103+
----
104+
NULL

0 commit comments

Comments
 (0)