@@ -3003,6 +3003,83 @@ struct ST_Dump {
3003
3003
}
3004
3004
};
3005
3005
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
+
3006
3083
// ======================================================================================================================
3007
3084
// ST_Extent
3008
3085
// ======================================================================================================================
@@ -9279,6 +9356,7 @@ void RegisterSpatialScalarFunctions(ExtensionLoader &loader) {
9279
9356
ST_DistanceWithin::Register (loader);
9280
9357
ST_Dump::Register (loader);
9281
9358
ST_EndPoint::Register (loader);
9359
+ ST_Expand::Register (loader);
9282
9360
ST_Extent::Register (loader);
9283
9361
ST_Extent_Approx::Register (loader);
9284
9362
// Op_IntersectApprox::Register(loader);
0 commit comments