@@ -3003,6 +3003,83 @@ struct ST_Dump {
30033003 }
30043004};
30053005
3006+
3007+ // ======================================================================================================================
3008+ // ST_Expand
3009+ // ======================================================================================================================
3010+
3011+ struct ST_Expand {
3012+
3013+ // ------------------------------------------------------------------------------------------------------------------
3014+ // GEOMETRY
3015+ // ------------------------------------------------------------------------------------------------------------------
3016+ static void Execute (DataChunk &args, ExpressionState &state, Vector &result) {
3017+ auto &lstate = LocalState::ResetAndGet (state);
3018+
3019+ BinaryExecutor::Execute<string_t , double , string_t >(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+
3082+
30063083// ======================================================================================================================
30073084// ST_Extent
30083085// ======================================================================================================================
@@ -9279,6 +9356,7 @@ void RegisterSpatialScalarFunctions(ExtensionLoader &loader) {
92799356 ST_DistanceWithin::Register (loader);
92809357 ST_Dump::Register (loader);
92819358 ST_EndPoint::Register (loader);
9359+ ST_Expand::Register (loader);
92829360 ST_Extent::Register (loader);
92839361 ST_Extent_Approx::Register (loader);
92849362 // Op_IntersectApprox::Register(loader);
0 commit comments