Skip to content

Commit d83faf8

Browse files
authored
Merge pull request #701 from Maxxen/v1.4-andium-dev
2 parents 5f0eba5 + 25838f3 commit d83faf8

File tree

3 files changed

+132
-1
lines changed

3 files changed

+132
-1
lines changed

src/spatial/index/rtree/rtree.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ RTreePointer RTree::MakePage(RTreeNodeType type) const {
3131
auto &alloc = type == RTreeNodeType::LEAF_PAGE ? *leaf_allocator : *node_allocator;
3232
pointer = alloc.New();
3333
pointer.SetMetadata(static_cast<uint8_t>(type));
34+
35+
// zero-initialize the node count
36+
auto &node = RefMutable(pointer);
37+
node.Clear();
38+
3439
return pointer;
3540
}
3641

@@ -655,4 +660,4 @@ void RTree::Print() const {
655660
Printer::Print(ToString());
656661
}
657662

658-
} // namespace duckdb
663+
} // namespace duckdb

src/spatial/modules/main/spatial_functions_scalar.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3003,6 +3003,82 @@ struct ST_Dump {
30033003
}
30043004
};
30053005

3006+
//======================================================================================================================
3007+
// ST_Expand
3008+
//======================================================================================================================
3009+
3010+
struct ST_Expand {
3011+
3012+
//------------------------------------------------------------------------------------------------------------------
3013+
// GEOMETRY
3014+
//------------------------------------------------------------------------------------------------------------------
3015+
static void Execute(DataChunk &args, ExpressionState &state, Vector &result) {
3016+
auto &lstate = LocalState::ResetAndGet(state);
3017+
3018+
BinaryExecutor::Execute<string_t, double, string_t>(
3019+
args.data[0], args.data[1], result, args.size(), [&](const string_t &blob, double distance) {
3020+
sgl::geometry geom;
3021+
lstate.Deserialize(blob, geom);
3022+
auto bbox = sgl::extent_xy::smallest();
3023+
3024+
if (sgl::ops::get_total_extent_xy(geom, bbox) == 0) {
3025+
const sgl::geometry empty(sgl::geometry_type::GEOMETRY_COLLECTION, false, false);
3026+
return lstate.Serialize(result, empty);
3027+
} else {
3028+
sgl::geometry expanded(sgl::geometry_type::POLYGON, false, false);
3029+
const auto min_x = bbox.min.x - distance;
3030+
const auto min_y = bbox.min.y - distance;
3031+
const auto max_x = bbox.max.x + distance;
3032+
const auto max_y = bbox.max.y + distance;
3033+
const double buffer[10] = {min_x, min_y, min_x, max_y, max_x, max_y, max_x, min_y, min_x, min_y};
3034+
3035+
sgl::geometry ring(sgl::geometry_type::LINESTRING, false, false);
3036+
ring.set_vertex_array(buffer, 5);
3037+
expanded.append_part(&ring);
3038+
return lstate.Serialize(result, expanded);
3039+
}
3040+
});
3041+
}
3042+
3043+
//------------------------------------------------------------------------------------------------------------------
3044+
// Documentation
3045+
//------------------------------------------------------------------------------------------------------------------
3046+
static constexpr auto DESCRIPTION = R"(
3047+
Expand the input geometry by the specified distance, returning a polygon.
3048+
3049+
`geom` is the input geometry.
3050+
3051+
`distance` is the target distance for the expansion, using the same units as the input geometry.
3052+
3053+
This is a planar operation and will not take into account the curvature of the earth.
3054+
)";
3055+
static constexpr auto EXAMPLE = R"(
3056+
SELECT ST_AsText(ST_Expand(ST_GeomFromText('POINT(20 30)'), 0.1));
3057+
)";
3058+
3059+
//------------------------------------------------------------------------------------------------------------------
3060+
// Register
3061+
//------------------------------------------------------------------------------------------------------------------
3062+
static void Register(ExtensionLoader &loader) {
3063+
FunctionBuilder::RegisterScalar(loader, "ST_Expand", [](ScalarFunctionBuilder &func) {
3064+
func.AddVariant([](ScalarFunctionVariantBuilder &variant) {
3065+
variant.AddParameter("geom", GeoTypes::GEOMETRY());
3066+
variant.AddParameter("distance", LogicalType::DOUBLE);
3067+
variant.SetReturnType(GeoTypes::GEOMETRY());
3068+
3069+
variant.SetInit(LocalState::Init);
3070+
variant.SetFunction(Execute);
3071+
});
3072+
3073+
func.SetDescription(DESCRIPTION);
3074+
func.SetExample(EXAMPLE);
3075+
3076+
func.SetTag("ext", "spatial");
3077+
func.SetTag("category", "property");
3078+
});
3079+
}
3080+
};
3081+
30063082
//======================================================================================================================
30073083
// ST_Extent
30083084
//======================================================================================================================
@@ -9302,6 +9378,7 @@ void RegisterSpatialScalarFunctions(ExtensionLoader &loader) {
93029378
ST_DistanceWithin::Register(loader);
93039379
ST_Dump::Register(loader);
93049380
ST_EndPoint::Register(loader);
9381+
ST_Expand::Register(loader);
93059382
ST_Extent::Register(loader);
93069383
ST_Extent_Approx::Register(loader);
93079384
// Op_IntersectApprox::Register(loader);

test/sql/geometry/st_expand.test

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# name: test/sql/geometry/st_expand.test
2+
# group: [geometry]
3+
4+
require spatial
5+
6+
query I
7+
SELECT ST_AsText(ST_Expand(ST_MakePoint(153.0, -38.0), 0.001));
8+
----
9+
POLYGON ((152.999 -38.001, 152.999 -37.999, 153.001 -37.999, 153.001 -38.001, 152.999 -38.001))
10+
11+
query I
12+
SELECT ST_AsText(ST_Expand(ST_MakePoint(153.0, -38.0), 0.0));
13+
----
14+
POLYGON ((153 -38, 153 -38, 153 -38, 153 -38, 153 -38))
15+
16+
query I
17+
SELECT ST_AsText(ST_Expand(ST_GeomFromText('POINT(20 30)'), 0.001));
18+
----
19+
POLYGON ((19.999 29.999, 19.999 30.001, 20.001 30.001, 20.001 29.999, 19.999 29.999))
20+
21+
query I
22+
SELECT ST_AsText(ST_Expand(ST_GeomFromText('GEOMETRYCOLLECTION(POINT(20 30))'), 0.001));
23+
----
24+
POLYGON ((19.999 29.999, 19.999 30.001, 20.001 30.001, 20.001 29.999, 19.999 29.999))
25+
26+
query I
27+
SELECT ST_AsText(ST_Expand(ST_GeomFromText('POLYGON((20 30, 21 30, 21 31, 20 31, 20 30))'), 0.1));
28+
----
29+
POLYGON ((19.9 29.9, 19.9 31.1, 21.1 31.1, 21.1 29.9, 19.9 29.9))
30+
31+
query I
32+
SELECT ST_AsText(ST_Expand(ST_GeomFromText('POLYGON((20 30, 21 30, 22 32, 21 31, 20 31, 20 30))'), 0.1));
33+
----
34+
POLYGON ((19.9 29.9, 19.9 32.1, 22.1 32.1, 22.1 29.9, 19.9 29.9))
35+
36+
query I
37+
SELECT ST_AsText(ST_Expand(ST_MakeEnvelope(20, 30, 21, 31), 0.1));
38+
----
39+
POLYGON ((19.9 29.9, 19.9 31.1, 21.1 31.1, 21.1 29.9, 19.9 29.9))
40+
41+
query I
42+
SELECT ST_AsText(ST_Expand(ST_MakeEnvelope(153.2, -38.8, 153.5, -38.7), 0.0));
43+
----
44+
POLYGON ((153.2 -38.8, 153.2 -38.7, 153.5 -38.7, 153.5 -38.8, 153.2 -38.8))
45+
46+
query I
47+
SELECT ST_AsText(ST_Expand(ST_GeomFromText('GEOMETRYCOLLECTION EMPTY'), 0.001));
48+
----
49+
GEOMETRYCOLLECTION EMPTY

0 commit comments

Comments
 (0)