From: Sandro Santilli Date: Thu, 11 Jun 2015 19:09:13 +0000 (+0000) Subject: Allow passing M factor to ST_Scale (#3062) X-Git-Tag: 2.2.0rc1~368 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4a03fe9b327989a07c3f4a675d072c41ab566c40;p=postgis Allow passing M factor to ST_Scale (#3062) git-svn-id: http://svn.osgeo.org/postgis/trunk@13654 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index 2cefa9146..9de3e0374 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,7 @@ PostGIS 2.2.0 * New Features * + - #3062, Allow passing M factor to ST_Scale (Sandro Santilli / Boundless) - #3139, ST_BoundingDiagonal (Sandro Santilli / Boundless) - #3129, ST_IsValidTrajectory (Sandro Santilli / Boundless) - #3128, ST_ClosestPointOfApproach (Sandro Santilli / Boundless) diff --git a/doc/reference_editor.xml b/doc/reference_editor.xml index f8b499a50..487bb1957 100644 --- a/doc/reference_editor.xml +++ b/doc/reference_editor.xml @@ -1260,6 +1260,12 @@ FROM (SELECT ST_LineToCurve(ST_Buffer(ST_GeomFromText('POINT(234 567)'), 3)) As float XFactor float YFactor + + + geometry ST_Scale + geometry geom + geometry factor + @@ -1273,15 +1279,24 @@ FROM (SELECT ST_LineToCurve(ST_Buffer(ST_GeomFromText('POINT(234 567)'), 3)) As ST_Scale(geomA, XFactor, YFactor, ZFactor) is short-hand for ST_Affine(geomA, XFactor, 0, 0, 0, YFactor, 0, 0, 0, ZFactor, 0, 0, 0). + +The version taking a geometry as the factor parameter +allows passing a 2d, 3dm, 3dz or 4d point to set scaling factor for all +supported dimensions. Missing dimensions in the factor +point are equivalant to no scaling the corresponding dimension. + + Prior to 1.3.4, this function crashes if used with geometries that contain CURVES. This is fixed in 1.3.4+ Availability: 1.1.0. Enhanced: 2.0.0 support for Polyhedral surfaces, Triangles and TIN was introduced. + Enhanced: 2.2.0 support for scaling all dimension (geometry parameter) was introduced. &P_support; &Z_support; &curve_support; &T_support; + &M_support; diff --git a/postgis/lwgeom_functions_basic.c b/postgis/lwgeom_functions_basic.c index c88673a1d..dffd39ca8 100644 --- a/postgis/lwgeom_functions_basic.c +++ b/postgis/lwgeom_functions_basic.c @@ -2799,3 +2799,51 @@ Datum ST_BoundingDiagonal(PG_FUNCTION_ARGS) PG_RETURN_POINTER(geom_out); } + +Datum ST_Scale(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(ST_Scale); +Datum ST_Scale(PG_FUNCTION_ARGS) +{ + GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P_COPY(0); /* will be modified */ + GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1); + GSERIALIZED *ret; + LWGEOM *lwgeom1 = lwgeom_from_gserialized(geom1); + LWGEOM *lwgeom2 = lwgeom_from_gserialized(geom2); + LWPOINT *lwpoint; + POINT4D factors; + + lwpoint = lwgeom_as_lwpoint(lwgeom2); + if ( lwpoint == NULL ) + { + lwgeom_free(lwgeom1); + lwgeom_free(lwgeom2); + PG_FREE_IF_COPY(geom1, 0); + PG_FREE_IF_COPY(geom2, 1); + lwpgerror("Scale factor geometry parameter must be a point"); + PG_RETURN_NULL(); + } + if ( ! lwpoint->point->npoints ) + { + /* empty point, return input untouched */ + lwgeom_free(lwgeom1); + lwgeom_free(lwgeom2); + PG_FREE_IF_COPY(geom2, 1); + PG_RETURN_POINTER(geom1); + } + getPoint4d_p(lwpoint->point, 0, &factors); + if ( ! FLAGS_GET_Z(lwpoint->flags ) ) factors.z = 1; + if ( ! FLAGS_GET_M(lwpoint->flags ) ) factors.m = 1; + + lwgeom_scale(lwgeom1, &factors); + + /* Construct GSERIALIZED */ + ret = geometry_serialize(lwgeom1); + + /* Cleanup */ + lwgeom_free(lwgeom1); + lwgeom_free(lwgeom2); + PG_FREE_IF_COPY(geom1, 0); + PG_FREE_IF_COPY(geom2, 1); + + PG_RETURN_POINTER(ret); +} diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in index 9d59ba5ca..22634d66a 100644 --- a/postgis/postgis.sql.in +++ b/postgis/postgis.sql.in @@ -944,10 +944,17 @@ CREATE OR REPLACE FUNCTION ST_Translate(geometry,float8,float8) AS 'SELECT ST_Translate($1, $2, $3, 0)' LANGUAGE 'sql' IMMUTABLE STRICT; +-- Availability: 2.2.0 +CREATE OR REPLACE FUNCTION ST_Scale(geometry,geometry) + RETURNS geometry + AS 'MODULE_PATHNAME', 'ST_Scale' + LANGUAGE 'c' IMMUTABLE STRICT; + -- Availability: 1.2.2 CREATE OR REPLACE FUNCTION ST_Scale(geometry,float8,float8,float8) RETURNS geometry AS 'SELECT ST_Affine($1, $2, 0, 0, 0, $3, 0, 0, 0, $4, 0, 0, 0)' + --AS 'SELECT ST_Scale($1, ST_Point($2, $3, $4))' LANGUAGE 'sql' IMMUTABLE STRICT; -- Availability: 1.2.2 diff --git a/regress/affine.sql b/regress/affine.sql index 1d5ef0999..0b9136aa0 100644 --- a/regress/affine.sql +++ b/regress/affine.sql @@ -8,6 +8,11 @@ select 'ST_Translate', ST_asewkt(ST_Translate('POINT(0 0 0)'::geometry, -3, -7, select 'ST_Scale', ST_asewkt(ST_Scale('POINT(1 1)'::geometry, 5, 5)); select 'ST_Scale', ST_asewkt(ST_Scale('POINT(1 1)'::geometry, 3, 2)); select 'ST_Scale', ST_asewkt(ST_Scale('POINT(10 20 -5)'::geometry, 4, 2, -8)); +SELECT 'ST_ScaleBOX', p && ST_Scale(p,ST_MakePoint(-10,1)) FROM ( + select 'POINT(1 1)'::geometry p ) foo; +select 'ST_ScaleM1', ST_asewkt(ST_Scale('POINT(10 20 -5 3)'::geometry, ST_MakePoint(4, 2, -8))); +select 'ST_ScaleM2', ST_asewkt(ST_Scale('POINT(-2 -1 3 2)'::geometry, ST_MakePointM(-2, 3, 4))); +select 'ST_ScaleM3', ST_asewkt(ST_Scale('POINT(10 20 -5 3)'::geometry, ST_MakePoint(-3, 2, -1, 3))); -- ST_Rotate select 'ST_Rotate', ST_asewkt(ST_SnapToGrid(ST_Rotate('POINT(1 1)'::geometry, pi()/2, 10.0, 20.0), 0.1)); diff --git a/regress/affine_expected b/regress/affine_expected index 639d06983..be9054fc8 100644 --- a/regress/affine_expected +++ b/regress/affine_expected @@ -3,6 +3,10 @@ ST_Translate|POINT(-3 -7 3) ST_Scale|POINT(5 5) ST_Scale|POINT(3 2) ST_Scale|POINT(40 40 40) +ST_ScaleBOX|f +ST_ScaleM1|POINT(40 40 40 3) +ST_ScaleM2|POINT(4 -3 3 8) +ST_ScaleM3|POINT(-30 40 5 9) ST_Rotate|POINT(29 11) ST_Rotate|POINT(-2 0) ST_Rotate|POINT(19 1)