Allow passing M factor to ST_Scale (#3062)
authorSandro Santilli <strk@keybit.net>
Thu, 11 Jun 2015 19:09:13 +0000 (19:09 +0000)
committerSandro Santilli <strk@keybit.net>
Thu, 11 Jun 2015 19:09:13 +0000 (19:09 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@13654 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
doc/reference_editor.xml
postgis/lwgeom_functions_basic.c
postgis/postgis.sql.in
regress/affine.sql
regress/affine_expected

diff --git a/NEWS b/NEWS
index 2cefa9146beb2915a589e19d45ec838d50ee4b90..9de3e037458945002f445ae913cb9ea6f5d518a5 100644 (file)
--- 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)
index f8b499a501d11e164c85f5d752938b24203a5bec..487bb19577997c6cb21fddb4e51c37d99ff9dfef 100644 (file)
@@ -1260,6 +1260,12 @@ FROM (SELECT ST_LineToCurve(ST_Buffer(ST_GeomFromText('POINT(234 567)'), 3)) As
                        <paramdef><type>float</type> <parameter>XFactor</parameter></paramdef>
                        <paramdef><type>float</type> <parameter>YFactor</parameter></paramdef>
                  </funcprototype>
+
+                 <funcprototype>
+                       <funcdef>geometry <function>ST_Scale</function></funcdef>
+                       <paramdef><type>geometry </type> <parameter>geom</parameter></paramdef>
+                       <paramdef><type>geometry</type> <parameter>factor</parameter></paramdef>
+                 </funcprototype>
                </funcsynopsis>
          </refsynopsisdiv>
 
@@ -1273,15 +1279,24 @@ FROM (SELECT ST_LineToCurve(ST_Buffer(ST_GeomFromText('POINT(234 567)'), 3)) As
                <note><para><code>ST_Scale(geomA,  XFactor, YFactor, ZFactor)</code>
                        is short-hand for <code>ST_Affine(geomA,  XFactor, 0, 0,  0, YFactor, 0,  0, 0, ZFactor,  0, 0, 0)</code>.</para></note>
 
+               <para>
+The version taking a geometry as the <varname>factor</varname> parameter
+allows passing a 2d, 3dm, 3dz or 4d point to set scaling factor for all
+supported dimensions. Missing dimensions in the <varname>factor</varname>
+point are equivalant to no scaling the corresponding dimension.
+    </para>
+
                <note><para>Prior to 1.3.4, this function crashes if used with geometries that contain CURVES.  This is fixed in 1.3.4+</para></note>
 
 
                <para>Availability: 1.1.0.</para>
                <para>Enhanced: 2.0.0 support for Polyhedral surfaces, Triangles and TIN was introduced.</para>
+               <para>Enhanced: 2.2.0 support for scaling all dimension (geometry parameter) was introduced.</para>
                <para>&P_support;</para>
                <para>&Z_support;</para>
                <para>&curve_support;</para>
                <para>&T_support;</para>
+               <para>&M_support;</para>
          </refsection>
 
 
index c88673a1dd46a9c1326d841a53a69b68e8400837..dffd39ca8cf5ee320865599e8619784e6d61c955 100644 (file)
@@ -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);
+}
index 9d59ba5cace3181c3884969239251e47db6f4455..22634d66ad90e83cdd07a94ecd9f5adfcbbd753e 100644 (file)
@@ -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
index 1d5ef099963db96bcc9df3032c9f375238faf98c..0b9136aa05a41d32c7f3c4f14a8cbac89988d8d7 100644 (file)
@@ -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));
index 639d06983af9a3fd88f956b1aeb5b7a58768a1b8..be9054fc8d77b1b124ff9f4b185969bab5198691 100644 (file)
@@ -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)