From: Bborie Park Date: Thu, 14 Jul 2011 20:11:39 +0000 (+0000) Subject: Code refactored for RASTER_dumpWKTPolygons to use same mechanisms for resultset gener... X-Git-Tag: 2.0.0alpha1~1203 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0c5dbac6c40167d3bbbadcdb9300add0465c71f8;p=postgis Code refactored for RASTER_dumpWKTPolygons to use same mechanisms for resultset generation (Datums instead of CStrings) as RASTER_metadata and other functions. SQL functions refactored to use one call to ST_Metadata for attributes rather than separate/multiple calls to ST_Skew*, ST_Scale*, ST_UpperLeft*. git-svn-id: http://svn.osgeo.org/postgis/trunk@7639 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/raster/rt_pg/rt_pg.c b/raster/rt_pg/rt_pg.c index ddaf0e4d2..585ef2adb 100644 --- a/raster/rt_pg/rt_pg.c +++ b/raster/rt_pg/rt_pg.c @@ -763,7 +763,6 @@ Datum RASTER_dumpAsWKTPolygons(PG_FUNCTION_ARGS) rt_raster raster = NULL; FuncCallContext *funcctx; TupleDesc tupdesc; - AttInMetadata *attinmeta; int nband; rt_geomval geomval; rt_geomval geomval2; @@ -772,7 +771,6 @@ Datum RASTER_dumpAsWKTPolygons(PG_FUNCTION_ARGS) int nElements; MemoryContext oldcontext; - /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { @@ -831,12 +829,8 @@ Datum RASTER_dumpAsWKTPolygons(PG_FUNCTION_ARGS) errmsg("function returning record called in context " "that cannot accept type record"))); - /* - * generate attribute metadata needed later to produce tuples from raw - * C strings - */ - attinmeta = TupleDescGetAttInMetadata(tupdesc); - funcctx->attinmeta = attinmeta; + BlessTupleDesc(tupdesc); + funcctx->tuple_desc = tupdesc; MemoryContextSwitchTo(oldcontext); } @@ -846,38 +840,30 @@ Datum RASTER_dumpAsWKTPolygons(PG_FUNCTION_ARGS) call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; - attinmeta = funcctx->attinmeta; + tupdesc = funcctx->tuple_desc; geomval2 = funcctx->user_fctx; if (call_cntr < max_calls) /* do when there is more left to send */ { - char **values; + int i; + bool *nulls = NULL; + int values_length = 3; + Datum values[values_length]; HeapTuple tuple; Datum result; POSTGIS_RT_DEBUGF(3, "call number %d", call_cntr); - /* - * Prepare a values array for building the returned tuple. - * This should be an array of C strings which will - * be processed later by the type input functions. - */ - values = (char **) palloc(3 * sizeof(char *)); - - values[0] = (char *) palloc( - (strlen(geomval2[call_cntr].geom) + 1) * sizeof(char)); - values[1] = (char *) palloc(18 * sizeof(char)); - values[2] = (char *) palloc(16 * sizeof(char)); + nulls = palloc(sizeof(bool) * values_length); + for (i = 0; i < values_length; i++) nulls[i] = FALSE; - snprintf(values[0], - (strlen(geomval2[call_cntr].geom) + 1) * sizeof(char), "%s", - geomval2[call_cntr].geom); - snprintf(values[1], 18 * sizeof(char), "%f", geomval2[call_cntr].val); - snprintf(values[2], 16 * sizeof(char), "%d", geomval2[call_cntr].srid); + values[0] = CStringGetTextDatum(geomval2[call_cntr].geom); + values[1] = Float8GetDatum(geomval2[call_cntr].val); + values[2] = Int32GetDatum(geomval2[call_cntr].srid); - POSTGIS_RT_DEBUGF(4, "Result %d, Polygon %s", call_cntr, values[0]); - POSTGIS_RT_DEBUGF(4, "Result %d, val %s", call_cntr, values[1]); - POSTGIS_RT_DEBUGF(4, "Result %d, val %s", call_cntr, values[2]); + POSTGIS_RT_DEBUGF(4, "Result %d, Polygon %s", call_cntr, geomval2[call_cntr].geom); + POSTGIS_RT_DEBUGF(4, "Result %d, val %s", call_cntr, geomval2[call_cntr].val); + POSTGIS_RT_DEBUGF(4, "Result %d, val %s", call_cntr, geomval2[call_cntr].srid); /** * Free resources. @@ -885,16 +871,13 @@ Datum RASTER_dumpAsWKTPolygons(PG_FUNCTION_ARGS) pfree(geomval2[call_cntr].geom); /* build a tuple */ - tuple = BuildTupleFromCStrings(attinmeta, values); + tuple = heap_form_tuple(tupdesc, values, nulls); /* make the tuple into a datum */ result = HeapTupleGetDatum(tuple); /* clean up (this is not really necessary) */ - pfree(values[0]); - pfree(values[1]); - pfree(values[2]); - pfree(values); + pfree(nulls); SRF_RETURN_NEXT(funcctx, result); diff --git a/raster/rt_pg/rtpostgis.sql.in.c b/raster/rt_pg/rtpostgis.sql.in.c index f43a30c5b..c9a3573c5 100644 --- a/raster/rt_pg/rtpostgis.sql.in.c +++ b/raster/rt_pg/rtpostgis.sql.in.c @@ -171,8 +171,22 @@ CREATE OR REPLACE FUNCTION st_makeemptyraster(width int, height int, upperleftx CREATE OR REPLACE FUNCTION st_makeemptyraster(rast raster) RETURNS raster - AS 'select st_makeemptyraster(st_width($1), st_height($1), st_upperleftx($1), st_upperlefty($1), st_scalex($1), st_scaley($1), st_skewx($1), st_skewy($1), st_srid($1))' - LANGUAGE 'SQL' IMMUTABLE STRICT; + AS $$ + DECLARE + w int; + h int; + ul_x double precision; + ul_y double precision; + scale_x double precision; + scale_y double precision; + skew_x double precision; + skew_y double precision; + sr_id int; + BEGIN + SELECT width, height, upperleftx, upperlefty, scalex, scaley, skewx, skewy, srid INTO w, h, ul_x, ul_y, scale_x, scale_y, skew_x, skew_y, sr_id FROM ST_Metadata(rast); + RETURN st_makeemptyraster(w, h, ul_x, ul_y, scale_x, scale_y, skew_x, skew_y, sr_id); + END; + $$ LANGUAGE 'plpgsql' IMMUTABLE STRICT; -- This function can not be STRICT, because nodataval can be NULL indicating that no nodata value should be set CREATE OR REPLACE FUNCTION st_addband(rast raster, index int, pixeltype text, initialvalue float8, nodataval float8) @@ -1718,33 +1732,42 @@ CREATE OR REPLACE FUNCTION st_georeference(rast raster, format text) RETURNS text AS $$ DECLARE - x numeric; + scale_x numeric; + scale_y numeric; + skew_x numeric; + skew_y numeric; + ul_x numeric; + ul_y numeric; + result text; BEGIN - x := st_scalex(rast)::numeric; - result := trunc(x, 10) || E'\n'; + SELECT scalex::numeric, scaley::numeric, skewx::numeric, skewy::numeric, upperleftx::numeric, upperlefty::numeric + INTO scale_x, scale_y, skew_x, skew_y, ul_x, ul_y FROM ST_Metadata(rast); + + -- scale x + result := trunc(scale_x, 10) || E'\n'; - x := st_skewy(rast)::numeric; - result := result || trunc(x, 10) || E'\n'; + -- skew y + result := result || trunc(skew_y, 10) || E'\n'; - x := st_skewx(rast)::numeric; - result := result || trunc(x, 10) || E'\n'; + -- skew x + result := result || trunc(skew_x, 10) || E'\n'; - x := st_scaley(rast)::numeric; - result := result || trunc(x, 10) || E'\n'; + -- scale y + result := result || trunc(scale_y, 10) || E'\n'; IF format = 'ESRI' THEN - x := (st_upperleftx(rast) + st_scalex(rast)*0.5)::numeric; - result := result || trunc(x, 10) || E'\n'; + -- upper left x + result := result || trunc((ul_x + scale_x * 0.5), 10) || E'\n'; - x := (st_upperlefty(rast) + st_scaley(rast)*0.5)::numeric; - result = result || trunc(x, 10) || E'\n'; + -- upper left y + result = result || trunc((ul_y + scale_y * 0.5), 10) || E'\n'; ELSE -- IF format = 'GDAL' THEN - x := st_upperleftx(rast)::numeric; - result := result || trunc(x, 10) || E'\n'; + -- upper left x + result := result || trunc(ul_x, 10) || E'\n'; - x := st_upperlefty(rast)::numeric; - result := result || trunc(x, 10) || E'\n'; + -- upper left y + result := result || trunc(ul_y, 10) || E'\n'; END IF; RETURN result; @@ -1981,12 +2004,15 @@ CREATE OR REPLACE FUNCTION st_pixelaspolygon(rast raster, band integer, x intege RETURNS geometry AS $$ DECLARE - w integer; - h integer; - scalex float8; - scaley float8; - skewx float8; - skewy float8; + w int; + h int; + scale_x float8; + scale_y float8; + skew_x float8; + skew_y float8; + ul_x float8; + ul_y float8; + sr_id int; x1 float8; y1 float8; x2 float8; @@ -1996,18 +2022,15 @@ CREATE OR REPLACE FUNCTION st_pixelaspolygon(rast raster, band integer, x intege x4 float8; y4 float8; BEGIN - scalex := st_scalex(rast); - skewx := st_skewy(rast); - skewy := st_skewx(rast); - scaley := st_scaley(rast); - x1 := scalex * (x - 1) + skewx * (y - 1) + st_upperleftx(rast); - y1 := scaley * (y - 1) + skewy * (x - 1) + st_upperlefty(rast); - x2 := x1 + scalex; - y2 := y1 + skewy; - x3 := x1 + scalex + skewx; - y3 := y1 + scaley + skewy; - x4 := x1 + skewx; - y4 := y1 + scaley; + SELECT scalex, scaley, skewx, skewy, upperleftx, upperlefty, srid INTO scale_x, scale_y, skew_x, skew_y, ul_x, ul_y, sr_id FROM ST_Metadata(rast); + x1 := scale_x * (x - 1) + skew_x * (y - 1) + ul_x; + y1 := scale_y * (y - 1) + skew_y * (x - 1) + ul_y; + x2 := x1 + scale_x; + y2 := y1 + skew_y; + x3 := x1 + scale_x + skew_x; + y3 := y1 + scale_y + skew_y; + x4 := x1 + skew_x; + y4 := y1 + scale_y; RETURN st_setsrid(st_makepolygon(st_makeline(ARRAY[st_makepoint(x1, y1), st_makepoint(x2, y2), st_makepoint(x3, y3), @@ -2015,7 +2038,7 @@ CREATE OR REPLACE FUNCTION st_pixelaspolygon(rast raster, band integer, x intege st_makepoint(x1, y1)] ) ), - st_srid(rast) + sr_id ); END; $$ @@ -2501,6 +2524,8 @@ CREATE OR REPLACE FUNCTION _st_intersects(geomin geometry, rast raster, band int bintersect boolean := FALSE; gtype text; scale float8; + w int; + h int; BEGIN -- Get the intersection between with the geometry. @@ -2521,7 +2546,7 @@ CREATE OR REPLACE FUNCTION _st_intersects(geomin geometry, rast raster, band int -- We create a minimalistic buffer around the intersection in order to scan every pixels -- that would touch the edge or intersect with the geometry - scale := st_scalex(rast) + st_skewy(rast); + SELECT (scalex * skewy), width, height INTO scale, w, h FROM ST_Metadata(rast); geomintersect := st_buffer(geomintersect, scale / 1000000); --RAISE NOTICE 'geomintersect2=%', astext(geomintersect); @@ -2556,14 +2581,14 @@ CREATE OR REPLACE FUNCTION _st_intersects(geomin geometry, rast raster, band int -- Make sure the range is not lower than 1. -- This can happen when world coordinate are exactly on the left border -- of the raster and that they do not span on more than one pixel. - x1 := int4smaller(int4larger(x1, 1), st_width(rast)); - y1 := int4smaller(int4larger(y1, 1), st_height(rast)); + x1 := int4smaller(int4larger(x1, 1), w); + y1 := int4smaller(int4larger(y1, 1), h); -- Also make sure the range does not exceed the width and height of the raster. -- This can happen when world coordinate are exactly on the lower right border -- of the raster. - x2 := int4smaller(x2, st_width(rast)); - y2 := int4smaller(y2, st_height(rast)); + x2 := int4smaller(x2, w); + y2 := int4smaller(y2, h); --RAISE NOTICE 'x1=%, y1=%, x2=%, y2=%', x1, y1, x2, y2;