From: Markus Schaber Date: Mon, 6 Jun 2005 07:58:40 +0000 (+0000) Subject: added scale() and transscale() functions (like transform()) X-Git-Tag: pgis_1_1_0~357 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e1bdb15c6cb818bccca2634b1c056786040444a8;p=postgis added scale() and transscale() functions (like transform()) git-svn-id: http://svn.osgeo.org/postgis/trunk@1735 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/CHANGES b/CHANGES index 1a4185b71..b5888a498 100644 --- 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 diff --git a/doc/postgis.xml b/doc/postgis.xml index be77a3f74..106737340 100644 --- a/doc/postgis.xml +++ b/doc/postgis.xml @@ -4410,7 +4410,27 @@ FROM geometry_table; Translates the geometry to a new location using the numeric - parameters as offsets. Ie: translate(geom,X,Y,Z). + parameters as offsets. Ie: translate(geom, X, Y, Z). + + + + + scale(geometry,float8,float8,float8) + + + scales the geometry to a new size by multiplying the + ordinates with the parameters. Ie: scale(geom, Xfactor, Yfactor, Zfactor). + + + + + transscale(geometry,float8,float8,float8,float8) + + + 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). diff --git a/jdbc2/.cvsignore b/jdbc2/.cvsignore index fead721cc..64f7f25dc 100644 --- a/jdbc2/.cvsignore +++ b/jdbc2/.cvsignore @@ -8,3 +8,4 @@ versionstamp test.log jtsbin eclipsebin +classpath diff --git a/lwgeom/BBOXCACHE_BEHAVIOURS b/lwgeom/BBOXCACHE_BEHAVIOURS index b538afd3b..598405a4b 100644 --- a/lwgeom/BBOXCACHE_BEHAVIOURS +++ b/lwgeom/BBOXCACHE_BEHAVIOURS @@ -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* diff --git a/lwgeom/liblwgeom.h b/lwgeom/liblwgeom.h index cf454f2f1..4a3e7d13f 100644 --- a/lwgeom/liblwgeom.h +++ b/lwgeom/liblwgeom.h @@ -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); diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index e90faf5a8..417764759 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -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; inpoints; 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; inpoints; 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; ingeometries; 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; jnrings; 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; inpoints; 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; inpoints; 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; ingeometries; 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; jnrings; 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) { diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index 952ad5b77..1d6831900 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -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)