]> granicus.if.org Git - postgis/commitdiff
added scale() and transscale() functions (like transform())
authorMarkus Schaber <markus@schabi.de>
Mon, 6 Jun 2005 07:58:40 +0000 (07:58 +0000)
committerMarkus Schaber <markus@schabi.de>
Mon, 6 Jun 2005 07:58:40 +0000 (07:58 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@1735 b70326c6-7e19-0410-871a-916f4a2858ee

CHANGES
doc/postgis.xml
jdbc2/.cvsignore
lwgeom/BBOXCACHE_BEHAVIOURS
lwgeom/liblwgeom.h
lwgeom/lwgeom_functions_basic.c
lwgeom/lwpostgis.sql.in

diff --git a/CHANGES b/CHANGES
index 1a4185b71447c97064a876aa0034db81dc8e6844..b5888a49811c207df57ee629556b40cc9d73f7b2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,7 @@ PostGIS 1.1.0CVS
          + Support for (Hex)(E)wkb
          + Autoprobing DriverWrapper for HexWKB / EWKT switching
        - full autoconf-based configuration
+       - added scale() and transscale() companion methods to translate()
 
 PostGIS 1.0.1
 2005/05/24
index be77a3f74802b0f8707408f9b006ce01e15624e5..1067373404757f9910028147b66da99d14fadb26 100644 (file)
@@ -4410,7 +4410,27 @@ FROM geometry_table;</literallayout>
 
           <listitem>
             <para>Translates the geometry to a new location using the numeric
-            parameters as offsets. Ie: translate(geom,X,Y,Z).</para>
+            parameters as offsets. Ie: translate(geom, X, Y, Z).</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>scale(geometry,float8,float8,float8)</term>
+
+          <listitem>
+            <para>scales the geometry to a new size by multiplying the
+            ordinates with the parameters. Ie: scale(geom, Xfactor, Yfactor, Zfactor).</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>transscale(geometry,float8,float8,float8,float8)</term>
+
+          <listitem>
+            <para>First, translates the geometry using the first two floats, then scales it 
+               using the second two floats, working in 2D only. Using 
+               transscale(geom, X, Y, XFactor, YFactor) effectively is an efficient shortcut 
+               for scale(translate(geom,X,Y,0),Xfactor,YFactor,1).</para>
           </listitem>
         </varlistentry>
 
index fead721cc1bf4859bbc707ecb0f89a947d36956d..64f7f25dc831d6eed6e7a348e0401d4bc50b783b 100644 (file)
@@ -8,3 +8,4 @@ versionstamp
 test.log
 jtsbin
 eclipsebin
+classpath
index b538afd3bc95291be7a6643f291b64bbcf22a987..598405a4b6a079ec322b666eac3ca2f69232de2a 100644 (file)
@@ -103,6 +103,7 @@ section also use it.
        ## transform eventually present box in input
        apply_grid(geometry, float8, float8, float8, float8); *LWG*
        translate(geometry,float8,float8,[float8]) *SRL*
+       scale(geometry,float8,float8,[float8]) *SRL*
 
        ## These use LWGEOM as a mean to access and modify SERIALIZED form
        reverse(geometry) *LWG* 
index cf454f2f152331197dca3abbf5e0585bd53afbd2..4a3e7d13fde91eef213ed68c9760c5bb8eb22b2a 100644 (file)
@@ -907,6 +907,10 @@ extern double distance2d_line_poly(LWLINE *line, LWPOLY *poly);
 extern double lwgeom_mindistance2d_recursive(uchar *lw1, uchar *lw2);
 extern void lwgeom_translate_recursive(uchar *serialized, double xoff, double yoff, double zoff);
 extern void lwgeom_translate_ptarray(POINTARRAY *pa, double xoff, double yoff, double zoff);
+extern void lwgeom_scale_recursive(uchar *serialized, double xfac, double yfac, double zfac);
+extern void lwgeom_scale_ptarray(POINTARRAY *pa, double xfac, double yfac, double zfac);
+extern void lwgeom_transscale_recursive(uchar *serialized, double xoff, double yoff, double xfac, double yfac);
+extern void lwgeom_transscale_ptarray(POINTARRAY *pa, double xoff, double yoff, double xfac, double yfac);
 extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad);
 extern int32 lwgeom_npoints(uchar *serialized);
 extern char ptarray_isccw(const POINTARRAY *pa);
index e90faf5a8c353d4b56f9ef4c42bb9f17744f6d15..417764759c7d8a62b7848cdce69b0f1ab6baec00 100644 (file)
@@ -34,6 +34,8 @@ Datum LWGEOM_perimeter_poly(PG_FUNCTION_ARGS);
 Datum LWGEOM_mindistance2d(PG_FUNCTION_ARGS);
 Datum LWGEOM_maxdistance2d_linestring(PG_FUNCTION_ARGS);
 Datum LWGEOM_translate(PG_FUNCTION_ARGS);
+Datum LWGEOM_scale(PG_FUNCTION_ARGS);
+Datum LWGEOM_transscale(PG_FUNCTION_ARGS);
 Datum LWGEOM_inside_circle_point(PG_FUNCTION_ARGS);
 Datum LWGEOM_collect(PG_FUNCTION_ARGS);
 Datum LWGEOM_accum(PG_FUNCTION_ARGS);
@@ -171,6 +173,192 @@ lwgeom_translate_recursive(uchar *serialized,
        pfree_inspected(inspected);
 }
 
+/*
+ * Scale a pointarray.
+ */
+void
+lwgeom_scale_ptarray(POINTARRAY *pa, double xfac, double yfac, double zfac)
+{
+       int i;
+       POINT3DZ p3d;
+       POINT2D p2d;
+
+       if ( TYPE_HASZ(pa->dims) )
+       {
+               for (i=0; i<pa->npoints; i++) {
+                       getPoint3dz_p(pa, i, &p3d);
+                       p3d.x *= xfac;
+                       p3d.y *= yfac;
+                       p3d.z *= zfac;
+                       memcpy(getPoint_internal(pa, i), &p3d,
+                               sizeof(POINT3DZ));
+               }
+       }
+       else
+       {
+               for (i=0; i<pa->npoints; i++) {
+                       getPoint2d_p(pa, i, &p2d);
+                       p2d.x *= xfac;
+                       p2d.y *= yfac;
+                       memcpy(getPoint_internal(pa, i), &p2d,
+                               sizeof(POINT2D));
+               }
+       }
+}
+
+void
+lwgeom_scale_recursive(uchar *serialized,
+       double xfac, double yfac, double zfac)
+{
+       LWGEOM_INSPECTED *inspected;
+       int i, j;
+
+       inspected = lwgeom_inspect(serialized);
+
+       // scan each object translating it
+       for (i=0; i<inspected->ngeometries; i++)
+       {
+               LWLINE *line=NULL;
+               LWPOINT *point=NULL;
+               LWPOLY *poly=NULL;
+               uchar *subgeom=NULL;
+
+               point = lwgeom_getpoint_inspected(inspected, i);
+               if (point !=NULL)
+               {
+                       lwgeom_scale_ptarray(point->point,
+                               xfac, yfac, zfac);
+                       lwgeom_release((LWGEOM *)point);
+                       continue;
+               }
+
+               poly = lwgeom_getpoly_inspected(inspected, i);
+               if (poly !=NULL)
+               {
+                       for (j=0; j<poly->nrings; j++)
+                       {
+                               lwgeom_scale_ptarray(poly->rings[j],
+                                       xfac, yfac, zfac);
+                       }
+                       lwgeom_release((LWGEOM *)poly);
+                       continue;
+               }
+
+               line = lwgeom_getline_inspected(inspected, i);
+               if (line != NULL)
+               {
+                       lwgeom_scale_ptarray(line->points,
+                               xfac, yfac, zfac);
+                       lwgeom_release((LWGEOM *)line);
+                       continue;
+               }
+
+               subgeom = lwgeom_getsubgeometry_inspected(inspected, i);
+               if ( subgeom == NULL )
+               {
+                       elog(ERROR, "lwgeom_getsubgeometry_inspected returned NULL??");
+               }
+               lwgeom_scale_recursive(subgeom, xfac, yfac, zfac);
+       }
+
+       pfree_inspected(inspected);
+}
+
+/*
+ * Transscale a pointarray.
+ */
+void
+lwgeom_transscale_ptarray(POINTARRAY *pa, double xoff, double yoff, double xfac, double yfac)
+{
+       int i;
+       POINT3DZ p3d;
+       POINT2D p2d;
+
+       if ( TYPE_HASZ(pa->dims) )
+       {
+               for (i=0; i<pa->npoints; i++) {
+                       getPoint3dz_p(pa, i, &p3d);
+                       p3d.x += xoff;
+                       p3d.x *= xfac;
+                       p3d.y += yoff;
+                       p3d.y *= yfac;
+                       /* Do nothing for z here */
+                       memcpy(getPoint_internal(pa, i), &p3d,
+                               sizeof(POINT3DZ));
+               }
+       }
+       else
+       {
+               for (i=0; i<pa->npoints; i++) {
+                       getPoint2d_p(pa, i, &p2d);
+                       p2d.x += xoff;
+                       p2d.x *= xfac;
+                       p2d.y += yoff;
+                       p2d.y *= yfac;
+                       memcpy(getPoint_internal(pa, i), &p2d,
+                               sizeof(POINT2D));
+               }
+       }
+}
+
+void
+lwgeom_transscale_recursive(uchar *serialized,
+       double xoff, double yoff, double xfac, double yfac)
+{
+       LWGEOM_INSPECTED *inspected;
+       int i, j;
+
+       inspected = lwgeom_inspect(serialized);
+
+       // scan each object translating it
+       for (i=0; i<inspected->ngeometries; i++)
+       {
+               LWLINE *line=NULL;
+               LWPOINT *point=NULL;
+               LWPOLY *poly=NULL;
+               uchar *subgeom=NULL;
+
+               point = lwgeom_getpoint_inspected(inspected, i);
+               if (point !=NULL)
+               {
+                       lwgeom_transscale_ptarray(point->point,
+                               xoff, yoff, xfac, yfac);
+                       lwgeom_release((LWGEOM *)point);
+                       continue;
+               }
+
+               poly = lwgeom_getpoly_inspected(inspected, i);
+               if (poly !=NULL)
+               {
+                       for (j=0; j<poly->nrings; j++)
+                       {
+                               lwgeom_transscale_ptarray(poly->rings[j],
+                                       xoff, yoff, xfac, yfac);
+                       }
+                       lwgeom_release((LWGEOM *)poly);
+                       continue;
+               }
+
+               line = lwgeom_getline_inspected(inspected, i);
+               if (line != NULL)
+               {
+                       lwgeom_transscale_ptarray(line->points,
+                               xoff, yoff, xfac, yfac);
+                       lwgeom_release((LWGEOM *)line);
+                       continue;
+               }
+
+               subgeom = lwgeom_getsubgeometry_inspected(inspected, i);
+               if ( subgeom == NULL )
+               {
+                       elog(ERROR, "lwgeom_getsubgeometry_inspected returned NULL??");
+               }
+               lwgeom_transscale_recursive(subgeom, xoff, yoff, xfac, yfac);
+       }
+
+       pfree_inspected(inspected);
+}
+
 //get summary info on a GEOMETRY
 PG_FUNCTION_INFO_V1(LWGEOM_summary);
 Datum LWGEOM_summary(PG_FUNCTION_ARGS)
@@ -1518,6 +1706,81 @@ Datum LWGEOM_translate(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(ret);
 }
 
+//scale geometry
+PG_FUNCTION_INFO_V1(LWGEOM_scale);
+Datum LWGEOM_scale(PG_FUNCTION_ARGS)
+{
+       PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
+       PG_LWGEOM *ret;
+       uchar *srl = SERIALIZED_FORM(geom);
+       BOX2DFLOAT4 box;
+       int hasbbox;
+
+       double xfac =  PG_GETARG_FLOAT8(1);
+       double yfac =  PG_GETARG_FLOAT8(2);
+       double zfac =  PG_GETARG_FLOAT8(3);
+
+       lwgeom_scale_recursive(srl, xfac, yfac, zfac);
+
+       /* COMPUTE_BBOX WHEN_SIMPLE */
+       hasbbox=getbox2d_p(srl, &box);
+       if ( hasbbox )
+       {
+               box.xmin *= xfac;
+               box.xmax *= xfac;
+               box.ymin *= yfac;
+               box.ymax *= yfac;
+       }
+
+       // Construct PG_LWGEOM 
+       ret = PG_LWGEOM_construct(srl, lwgeom_getsrid(srl), hasbbox);
+
+       // Release copy of detoasted input.
+       pfree(geom);
+
+       PG_RETURN_POINTER(ret);
+}
+
+//transscale geometry
+PG_FUNCTION_INFO_V1(LWGEOM_transscale);
+Datum LWGEOM_transscale(PG_FUNCTION_ARGS)
+{
+       PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
+       PG_LWGEOM *ret;
+       uchar *srl = SERIALIZED_FORM(geom);
+       BOX2DFLOAT4 box;
+       int hasbbox;
+
+       double xoff =  PG_GETARG_FLOAT8(1);
+       double yoff =  PG_GETARG_FLOAT8(2);
+       double xfac =  PG_GETARG_FLOAT8(3);
+       double yfac =  PG_GETARG_FLOAT8(4);
+
+       lwgeom_transscale_recursive(srl, xoff, yoff, xfac, yfac);
+
+       /* COMPUTE_BBOX WHEN_SIMPLE */
+       hasbbox=getbox2d_p(srl, &box);
+       if ( hasbbox )
+       {
+               box.xmin += xoff;
+               box.xmax += xoff;
+               box.ymin += yoff;
+               box.ymax += yoff;
+               box.xmin *= xfac;
+               box.xmax *= xfac;
+               box.ymin *= yfac;
+               box.ymax *= yfac;
+       }
+
+       // Construct PG_LWGEOM 
+       ret = PG_LWGEOM_construct(srl, lwgeom_getsrid(srl), hasbbox);
+
+       // Release copy of detoasted input.
+       pfree(geom);
+
+       PG_RETURN_POINTER(ret);
+}
+
 PG_FUNCTION_INFO_V1(LWGEOM_inside_circle_point);
 Datum LWGEOM_inside_circle_point(PG_FUNCTION_ARGS)
 {
index 952ad5b774231639bcd929be02fcad6d12f1e229..1d6831900e41336f1b74652c0f42540b6b9961df 100644 (file)
@@ -870,6 +870,21 @@ CREATEFUNCTION translate(geometry,float8,float8)
        AS ' SELECT translate($1, $2, $3, 0) '
        LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict);
 
+CREATEFUNCTION scale(geometry,float8,float8,float8)
+       RETURNS geometry
+       AS '@MODULE_FILENAME@', 'LWGEOM_scale'
+       LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict) ;
+
+CREATEFUNCTION scale(geometry,float8,float8)
+       RETURNS geometry
+       AS ' SELECT scale($1, $2, $3, 1) '
+       LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict);
+
+CREATEFUNCTION transscale(geometry,float8,float8,float8,float8)
+       RETURNS geometry
+       AS '@MODULE_FILENAME@', 'LWGEOM_transscale'
+       LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict) ;
+
 --- CHIP functions
 
 CREATEFUNCTION srid(chip)