Datum RASTER_sameAlignment(PG_FUNCTION_ARGS);
/* two-raster MapAlgebra */
-Datum RASTER_mapAlgebra2Expr(PG_FUNCTION_ARGS);
+Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS);
/*
Datum RASTER_mapAlgebra2Fct(PG_FUNCTION_ARGS);
*/
}
/**
- * Two raster MapAlgebra
+ * Two raster MapAlgebra using expressions
*/
-PG_FUNCTION_INFO_V1(RASTER_mapAlgebra2Expr);
-Datum RASTER_mapAlgebra2Expr(PG_FUNCTION_ARGS)
+PG_FUNCTION_INFO_V1(RASTER_mapAlgebra2);
+Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS)
{
const int set_count = 2;
rt_pgraster *pgrast;
uint32_t bandindex[2] = {0};
rt_raster _rast[2] = {NULL};
rt_band _band[2] = {NULL};
+ int _hasnodata[2] = {0};
+ double _nodataval[2] = {0};
+ double _offset[4] = {0.};
+ double _rastoffset[2][4] = {{0.}};
+ int _haspixel[2] = {0};
+ double _pixel[2] = {0};
+ uint16_t _dim[2][2] = {{0}};
char *pixtypename = NULL;
rt_pixtype pixtype = PT_END;
char *extenttypename = NULL;
rt_extenttype extenttype = ET_INTERSECTION;
+
+ rt_raster raster = NULL;
+ rt_band band = NULL;
+ uint16_t dim[2] = {0};
+ int haspixel = 0;
+ double pixel = 0.;
double nodataval = 0;
- int _hasnodata[2] = {0};
- double _nodataval[2] = {0};
+ double gt[6] = {0.};
- int hasnodatanodataval = 0;
- double nodatanodataval = 0;
+ Oid calltype = InvalidOid;
int spicount = 3;
uint16_t exprpos[3] = {4, 7, 8};
bool isnull = FALSE;
int hasargval[3] = {0};
double argval[3] = {0.};
+ int hasnodatanodataval = 0;
+ double nodatanodataval = 0;
- double _offset[4] = {0.};
- double _rastoffset[2][4] = {{0.}};
- int _haspixel[2] = {0};
- double _pixel[2] = {0};
- uint16_t _dim[2][2] = {{0}};
-
- rt_raster raster = NULL;
- rt_band band = NULL;
- uint16_t dim[2] = {0};
- int haspixel = 0;
- double pixel = 0.;
+ Oid ufcnoid = InvalidOid;
+ FmgrInfo uflinfo;
+ FunctionCallInfoData ufcinfo;
+ int ufcnullcount = 0;
uint32_t i = 0;
uint32_t j = 0;
int _x = 0;
int _y = 0;
int err;
- double gt[6] = {0.};
int aligned = 0;
int len = 0;
- POSTGIS_RT_DEBUG(3, "Starting RASTER_mapAlgebra2Expr");
+ POSTGIS_RT_DEBUG(3, "Starting RASTER_mapAlgebra2");
for (i = 0, j = 0; i < set_count; i++) {
if (!PG_ARGISNULL(j)) {
/* raster */
rast[i] = rt_raster_deserialize(pgrast, FALSE);
if (!rast[i]) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Could not deserialize the %s raster", i < 1 ? "first" : "second");
+ elog(ERROR, "RASTER_mapAlgebra2: Could not deserialize the %s raster", i < 1 ? "first" : "second");
for (k = 0; k < i; k++) {
if (rast[k] != NULL) rt_raster_destroy(rast[k]);
}
raster = rt_raster_new(0, 0);
if (raster == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to create empty raster");
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to create empty raster");
for (k = 0; k < i; k++) {
if (rast[k] != NULL) rt_raster_destroy(rast[k]);
}
_dim[j][1]
);
if (_rast[i] == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to create nodata raster");
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to create nodata raster");
rt_raster_destroy(_rast[j]);
PG_RETURN_NULL();
}
/* same alignment */
if (!rt_raster_same_alignment(_rast[0], _rast[1], &aligned)) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to test for alignment on the two rasters");
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to test for alignment on the two rasters");
for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
PG_RETURN_NULL();
}
/* Get the pixel type index */
pixtype = rt_pixtype_index_from_name(pixtypename);
if (pixtype == PT_END ) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Invalid pixel type: %s", pixtypename);
+ elog(ERROR, "RASTER_mapAlgebra2: Invalid pixel type: %s", pixtypename);
for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
PG_RETURN_NULL();
}
&err, _offset
);
if (!err) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to get output raster of correct extent");
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to get output raster of correct extent");
for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
PG_RETURN_NULL();
}
dim[1] = rt_raster_get_height(raster);
i = 2;
+ /* handle special cases for extent */
switch (extenttype) {
case ET_FIRST:
i = 0;
raster = rt_raster_new(0, 0);
if (raster == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to create no band raster");
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to create no band raster");
for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
PG_RETURN_NULL();
}
_band[i] = rt_raster_get_band(_rast[i], bandindex[i] - 1);
if (_band[i] == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to get band %d of the %s raster",
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to get band %d of the %s raster",
bandindex[i],
(i < 1 ? "FIRST" : "SECOND")
);
1, nodataval,
0
) < 0) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to add new band to output raster");
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to add new band to output raster");
for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
rt_raster_destroy(raster);
PG_RETURN_NULL();
/* get output band */
band = rt_raster_get_band(raster, 0);
if (band == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to get newly added band of output raster");
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to get newly added band of output raster");
for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
rt_raster_destroy(raster);
PG_RETURN_NULL();
rt_band_get_nodata(band)
);
- /* connect SPI */
- if (SPI_connect() != SPI_OK_CONNECT) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to connect to the SPI manager");
- for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
- rt_raster_destroy(raster);
- PG_RETURN_NULL();
- }
-
/*
- process expressions
-
- exprpos elements are:
- 4 - expression => spiplan[0]
- 7 - nodata1expr => spiplan[1]
- 8 - nodata2expr => spiplan[2]
+ determine who called this function
+ Arg 4 will either be text or regprocedure
*/
- for (i = 0; i < spicount; i++) {
- if (!PG_ARGISNULL(exprpos[i])) {
- expr = strtoupper(text_to_cstring(PG_GETARG_TEXT_P(exprpos[i])));
- POSTGIS_RT_DEBUGF(3, "raw expr #%d: %s", i, expr);
- expr = replace(expr, "RAST1", "$1", &len);
- if (len) {
- argcount[i]++;
- argexists[i][0] = 1;
- }
- expr = replace(expr, "RAST2", (argexists[i][0] ? "$2" : "$1"), &len);
- if (len) {
- argcount[i]++;
- argexists[i][1] = 1;
- }
+ POSTGIS_RT_DEBUG(3, "checking parameter type for arg 4");
+ calltype = get_fn_expr_argtype(fcinfo->flinfo, 4);
+
+ switch(calltype) {
+ case TEXTOID: {
+ POSTGIS_RT_DEBUG(3, "arg 4 is \"expression\"!");
- len = strlen("SELECT (") + strlen(expr) + strlen(")::double precision");
- sql = (char *) palloc(len + 1);
- if (sql == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to allocate memory for expression parameter %d", exprpos[i]);
+ /* connect SPI */
+ if (SPI_connect() != SPI_OK_CONNECT) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to connect to the SPI manager");
for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
rt_raster_destroy(raster);
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
PG_RETURN_NULL();
}
- strncpy(sql, "SELECT (", strlen("SELECT ("));
- strncpy(sql + strlen("SELECT ("), expr, strlen(expr));
- strncpy(sql + strlen("SELECT (") + strlen(expr), ")::double precision", strlen(")::double precision"));
- sql[len] = '\0';
+ /* reset hasargval */
+ memset(hasargval, 0, spicount);
+
+ /*
+ process expressions
+
+ exprpos elements are:
+ 4 - expression => spiplan[0]
+ 7 - nodata1expr => spiplan[1]
+ 8 - nodata2expr => spiplan[2]
+ */
+ for (i = 0; i < spicount; i++) {
+ if (!PG_ARGISNULL(exprpos[i])) {
+ expr = strtoupper(text_to_cstring(PG_GETARG_TEXT_P(exprpos[i])));
+ POSTGIS_RT_DEBUGF(3, "raw expr #%d: %s", i, expr);
+ expr = replace(expr, "RAST1", "$1", &len);
+ if (len) {
+ argcount[i]++;
+ argexists[i][0] = 1;
+ }
+ expr = replace(expr, "RAST2", (argexists[i][0] ? "$2" : "$1"), &len);
+ if (len) {
+ argcount[i]++;
+ argexists[i][1] = 1;
+ }
- POSTGIS_RT_DEBUGF(3, "sql #%d: %s", i, sql);
+ len = strlen("SELECT (") + strlen(expr) + strlen(")::double precision");
+ sql = (char *) palloc(len + 1);
+ if (sql == NULL) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to allocate memory for expression parameter %d", exprpos[i]);
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
+ PG_RETURN_NULL();
+ }
- /* create prepared plan */
- if (argcount[i]) {
- argtype = (Oid *) palloc(argcount[i] * sizeof(Oid));
- if (argtype == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to allocate memory for prepared plan argtypes of expression parameter %d", exprpos[i]);
+ strncpy(sql, "SELECT (", strlen("SELECT ("));
+ strncpy(sql + strlen("SELECT ("), expr, strlen(expr));
+ strncpy(sql + strlen("SELECT (") + strlen(expr), ")::double precision", strlen(")::double precision"));
+ sql[len] = '\0';
- for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
- rt_raster_destroy(raster);
+ POSTGIS_RT_DEBUGF(3, "sql #%d: %s", i, sql);
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
+ /* create prepared plan */
+ if (argcount[i]) {
+ argtype = (Oid *) palloc(argcount[i] * sizeof(Oid));
+ if (argtype == NULL) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to allocate memory for prepared plan argtypes of expression parameter %d", exprpos[i]);
- pfree(sql);
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
- PG_RETURN_NULL();
- }
- for (j = 0; j < argcount[i]; j++) argtype[j] = FLOAT8OID;
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
- spiplan[i] = SPI_prepare(sql, argcount[i], argtype);
- if (spiplan[i] == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to create prepared plan of expression parameter %d", exprpos[i]);
+ pfree(sql);
- for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
- rt_raster_destroy(raster);
+ PG_RETURN_NULL();
+ }
+ for (j = 0; j < argcount[i]; j++) argtype[j] = FLOAT8OID;
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
+ spiplan[i] = SPI_prepare(sql, argcount[i], argtype);
+ if (spiplan[i] == NULL) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to create prepared plan of expression parameter %d", exprpos[i]);
- pfree(sql);
- pfree(argtype);
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
- PG_RETURN_NULL();
- }
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
- pfree(argtype);
- }
- /* no args, just execute query */
- else {
- err = SPI_execute(sql, TRUE, 0);
- if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to evaluate expression parameter %d", exprpos[i]);
+ pfree(sql);
+ pfree(argtype);
- for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
- rt_raster_destroy(raster);
+ PG_RETURN_NULL();
+ }
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
+ pfree(argtype);
+ }
+ /* no args, just execute query */
+ else {
+ err = SPI_execute(sql, TRUE, 0);
+ if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to evaluate expression parameter %d", exprpos[i]);
- pfree(sql);
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
- PG_RETURN_NULL();
- }
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
- /* get output of prepared plan */
- tupdesc = SPI_tuptable->tupdesc;
- tuptable = SPI_tuptable;
- tuple = tuptable->vals[0];
+ pfree(sql);
- datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
- if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to get result of expression parameter %d", exprpos[i]);
+ PG_RETURN_NULL();
+ }
- for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
- rt_raster_destroy(raster);
+ /* get output of prepared plan */
+ tupdesc = SPI_tuptable->tupdesc;
+ tuptable = SPI_tuptable;
+ tuple = tuptable->vals[0];
- if (SPI_tuptable) SPI_freetuptable(tuptable);
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
+ datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
+ if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to get result of expression parameter %d", exprpos[i]);
- pfree(sql);
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
- PG_RETURN_NULL();
- }
+ if (SPI_tuptable) SPI_freetuptable(tuptable);
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
- if (!isnull) {
- hasargval[i] = 1;
- argval[i] = DatumGetFloat8(datum);
- }
+ pfree(sql);
- if (SPI_tuptable) SPI_freetuptable(tuptable);
+ PG_RETURN_NULL();
+ }
+
+ if (!isnull) {
+ hasargval[i] = 1;
+ argval[i] = DatumGetFloat8(datum);
+ }
+
+ if (SPI_tuptable) SPI_freetuptable(tuptable);
+ }
+
+ pfree(sql);
+ }
+ else
+ spiempty++;
}
- pfree(sql);
- }
- else
- spiempty++;
- }
+ /* nodatanodataval */
+ if (!PG_ARGISNULL(9)) {
+ hasnodatanodataval = 1;
+ nodatanodataval = PG_GETARG_FLOAT8(9);
+ }
+ else
+ hasnodatanodataval = 0;
+ } break;
+ case REGPROCEDUREOID: {
+ POSTGIS_RT_DEBUG(3, "arg 4 is \"userfunction\"!");
+ if (!PG_ARGISNULL(4)) {
+ ufcnullcount = 0;
+ ufcnoid = PG_GETARG_OID(4);
+
+ /* get function info */
+ fmgr_info(ufcnoid, &uflinfo);
+
+ /* prep function call data */
+#if POSTGIS_PGSQL_VERSION <= 90
+ InitFunctionCallInfoData(ufcinfo, &uflinfo, 3, InvalidOid, NULL);
+#else
+ InitFunctionCallInfoData(ufcinfo, &uflinfo, 3, InvalidOid, NULL, NULL);
+#endif
+ memset(ufcinfo.argnull, FALSE, 3);
- /* nodatanodataval */
- if (!PG_ARGISNULL(9)) {
- hasnodatanodataval = 1;
- nodatanodataval = PG_GETARG_FLOAT8(9);
+ if (!PG_ARGISNULL(7)) {
+ ufcinfo.arg[2] = PG_GETARG_DATUM(7);
+ }
+ else {
+ ufcinfo.arg[2] = (Datum) NULL;
+ ufcinfo.argnull[2] = TRUE;
+ ufcnullcount++;
+ }
+ }
+ } break;
+ default:
+ elog(ERROR, "RASTER_mapAlgebra2: Invalid data type for expression or userfunction");
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
+ PG_RETURN_NULL();
+ break;
}
- else
- hasnodatanodataval = 0;
/* loop over pixels */
/* if any expression present, run */
- if (spiempty != spicount || hasnodatanodataval) {
+ if ((
+ (calltype == TEXTOID) && (
+ (spiempty != spicount) || hasnodatanodataval
+ )
+ ) || (
+ (calltype == REGPROCEDUREOID) && (ufcnoid != InvalidOid)
+ )) {
for (x = 0; x < dim[0]; x++) {
for (y = 0; y < dim[1]; y++) {
) {
err = rt_band_get_pixel(_band[i], _x, _y, &(_pixel[i]));
if (err < 0) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to get pixel of %s raster", (i < 1 ? "FIRST" : "SECOND"));
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to get pixel of %s raster", (i < 1 ? "FIRST" : "SECOND"));
for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
rt_raster_destroy(raster);
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
+ if (calltype == TEXTOID) {
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
+ }
PG_RETURN_NULL();
}
haspixel = 0;
- /* which prepared plan to use? */
- /* !pixel0 && !pixel1 */
- /* use nodatanodataval */
- if (!_haspixel[0] && !_haspixel[1])
- i = 3;
- /* pixel0 && !pixel1 */
- /* run spiplan[2] (nodata2expr) */
- else if (_haspixel[0] && !_haspixel[1])
- i = 2;
- /* !pixel0 && pixel1 */
- /* run spiplan[1] (nodata1expr) */
- else if (!_haspixel[0] && _haspixel[1])
- i = 1;
- /* pixel0 && pixel1 */
- /* run spiplan[0] (expression) */
- else
- i = 0;
+ switch (calltype) {
+ case TEXTOID: {
+ /* which prepared plan to use? */
+ /* !pixel0 && !pixel1 */
+ /* use nodatanodataval */
+ if (!_haspixel[0] && !_haspixel[1])
+ i = 3;
+ /* pixel0 && !pixel1 */
+ /* run spiplan[2] (nodata2expr) */
+ else if (_haspixel[0] && !_haspixel[1])
+ i = 2;
+ /* !pixel0 && pixel1 */
+ /* run spiplan[1] (nodata1expr) */
+ else if (!_haspixel[0] && _haspixel[1])
+ i = 1;
+ /* pixel0 && pixel1 */
+ /* run spiplan[0] (expression) */
+ else
+ i = 0;
- /* process values */
- if (i == 3) {
- if (hasnodatanodataval) {
- haspixel = 1;
- pixel = nodatanodataval;
- }
- }
- /* prepared plan exists */
- else if (spiplan[i] != NULL) {
- POSTGIS_RT_DEBUGF(5, "Using prepared plan: %d", i);
+ /* process values */
+ if (i == 3) {
+ if (hasnodatanodataval) {
+ haspixel = 1;
+ pixel = nodatanodataval;
+ }
+ }
+ /* has an evaluated value */
+ else if (hasargval[i]) {
+ haspixel = 1;
+ pixel = argval[i];
+ }
+ /* prepared plan exists */
+ else if (spiplan[i] != NULL) {
+ POSTGIS_RT_DEBUGF(5, "Using prepared plan: %d", i);
+
+ /* expression has argument(s) */
+ if (argcount[i]) {
+ values = (Datum *) palloc(sizeof(Datum) * argcount[i]);
+ if (values == NULL) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to allocate memory for value parameters of prepared statement %d", i);
+
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
+
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
+
+ PG_RETURN_NULL();
+ }
+
+ nulls = (bool *) palloc(sizeof(bool) * argcount[i]);
+ if (nulls == NULL) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to allocate memory for NULL parameters of prepared statement %d", i);
+
+ pfree(values);
+
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
+
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
+
+ PG_RETURN_NULL();
+ }
+ memset(nulls, FALSE, argcount[i]);
+
+ /* two arguments */
+ if (argcount[i] > 1) {
+ for (j = 0; j < argcount[i]; j++) {
+ if (_isempty[j] || !_haspixel[j])
+ nulls[j] = TRUE;
+ else
+ values[j] = Float8GetDatum(_pixel[j]);
+ }
+ }
+ /* only one argument */
+ else {
+ if (argexists[i][0])
+ j = 0;
+ else
+ j = 1;
+
+ if (_isempty[j] || !_haspixel[j]) {
+ POSTGIS_RT_DEBUG(5, "using null");
+ nulls[0] = TRUE;
+ }
+ else {
+ POSTGIS_RT_DEBUGF(5, "using value %f", _pixel[j]);
+ values[0] = Float8GetDatum(_pixel[j]);
+ }
+ }
+ }
- /* expression has argument(s) */
- if (argcount[i]) {
- values = (Datum *) palloc(sizeof(Datum) * argcount[i]);
- if (values == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to allocate memory for value parameters of prepared statement %d", i);
+ /* run prepared plan */
+ err = SPI_execute_plan(spiplan[i], values, nulls, TRUE, 1);
+ if (values != NULL) pfree(values);
+ if (nulls != NULL) pfree(nulls);
+ if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unexpected error when running prepared statement %d", i);
- for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
- rt_raster_destroy(raster);
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
- PG_RETURN_NULL();
- }
+ PG_RETURN_NULL();
+ }
- nulls = (bool *) palloc(sizeof(bool) * argcount[i]);
- if (nulls == NULL) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to allocate memory for NULL parameters of prepared statement %d", i);
+ /* get output of prepared plan */
+ tupdesc = SPI_tuptable->tupdesc;
+ tuptable = SPI_tuptable;
+ tuple = tuptable->vals[0];
- pfree(values);
+ datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
+ if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to get result of prepared statement %d", i);
- for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
- rt_raster_destroy(raster);
+ for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
+ rt_raster_destroy(raster);
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
+ if (SPI_tuptable) SPI_freetuptable(tuptable);
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
- PG_RETURN_NULL();
- }
- memset(nulls, FALSE, argcount[i]);
-
- /* two arguments */
- if (argcount[i] > 1) {
- for (j = 0; j < argcount[i]; j++) {
- if (_isempty[j] || !_haspixel[j])
- nulls[j] = TRUE;
- else
- values[j] = Float8GetDatum(_pixel[j]);
+ PG_RETURN_NULL();
+ }
+
+ if (!isnull) {
+ haspixel = 1;
+ pixel = DatumGetFloat8(datum);
}
+
+ if (SPI_tuptable) SPI_freetuptable(tuptable);
}
- /* only one argument */
- else {
- if (argexists[i][0])
- j = 0;
- else
- j = 1;
-
- if (_isempty[j] || !_haspixel[j]) {
- POSTGIS_RT_DEBUG(5, "using null");
- nulls[0] = TRUE;
+ } break;
+ case REGPROCEDUREOID: {
+ /* build fcnarg */
+ for (i = 0; i < set_count; i++) {
+ ufcinfo.arg[i] = Float8GetDatum(_pixel[i]);
+
+ if (_haspixel[i]) {
+ ufcinfo.argnull[i] = FALSE;
+ ufcnullcount--;
}
else {
- POSTGIS_RT_DEBUGF(5, "using value %f", _pixel[j]);
- values[0] = Float8GetDatum(_pixel[j]);
+ ufcinfo.argnull[i] = TRUE;
+ ufcnullcount++;
}
}
- }
-
- /* run prepared plan */
- err = SPI_execute_plan(spiplan[i], values, nulls, TRUE, 1);
- if (values != NULL) pfree(values);
- if (nulls != NULL) pfree(nulls);
- if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unexpected error when running prepared statement %d", i);
-
- for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
- rt_raster_destroy(raster);
-
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
-
- PG_RETURN_NULL();
- }
-
- /* get output of prepared plan */
- tupdesc = SPI_tuptable->tupdesc;
- tuptable = SPI_tuptable;
- tuple = tuptable->vals[0];
-
- datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
- if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to get result of prepared statement %d", i);
-
- for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
- rt_raster_destroy(raster);
-
- if (SPI_tuptable) SPI_freetuptable(tuptable);
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
- PG_RETURN_NULL();
- }
+ /* function is strict and null parameter is passed */
+ /* http://archives.postgresql.org/pgsql-general/2011-11/msg00424.php */
+ if (uflinfo.fn_strict && ufcnullcount)
+ break;
- if (!isnull) {
- haspixel = 1;
- pixel = DatumGetFloat8(datum);
- }
+ datum = FunctionCallInvoke(&ufcinfo);
- if (SPI_tuptable) SPI_freetuptable(tuptable);
- }
- /* has an evaluated value */
- else if (hasargval[i]) {
- haspixel = 1;
- pixel = argval[i];
+ /* result is not null*/
+ if (!ufcinfo.isnull) {
+ haspixel = 1;
+ pixel = DatumGetFloat8(datum);
+ }
+ } break;
}
/* burn pixel if haspixel != 0 */
if (haspixel) {
if (rt_band_set_pixel(band, x, y, pixel) < 0) {
- elog(ERROR, "RASTER_mapAlgebra2Expr: Unable to set pixel value of output raster");
+ elog(ERROR, "RASTER_mapAlgebra2: Unable to set pixel value of output raster");
for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
rt_raster_destroy(raster);
- for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
- SPI_finish();
+ if (calltype == TEXTOID) {
+ for (k = 0; k < spicount; k++) SPI_freeplan(spiplan[k]);
+ SPI_finish();
+ }
PG_RETURN_NULL();
}
}
POSTGIS_RT_DEBUGF(5, "(x, y, val) = (%d, %d, %f)", x, y, haspixel ? pixel : nodataval);
- }
- }
+
+ } /* y: height */
+ } /* x: width */
}
/* CLEANUP */
- for (i = 0; i < spicount; i++) {
- if (spiplan[i] != NULL) SPI_freeplan(spiplan[i]);
+ if (calltype == TEXTOID) {
+ for (i = 0; i < spicount; i++) {
+ if (spiplan[i] != NULL) SPI_freeplan(spiplan[i]);
+ }
+ SPI_finish();
}
- SPI_finish();
for (k = 0; k < set_count; k++) {
if (_rast[k] != NULL) rt_raster_destroy(_rast[k]);
rt_raster_destroy(raster);
if (!pgrast) PG_RETURN_NULL();
+ POSTGIS_RT_DEBUG(3, "Finished RASTER_mapAlgebra2");
+
SET_VARSIZE(pgrast, pgrast->size);
PG_RETURN_POINTER(pgrast);
}
+/**
+ * Two raster MapAlgebra using user function
+ */
+ /*
+PG_FUNCTION_INFO_V1(RASTER_mapAlgebra2Fct);
+Datum RASTER_mapAlgebra2Fct(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_NULL();
+}
+*/
+
/* ---------------------------------------------------------------- */
/* Memory allocation / error reporting hooks */
/* ---------------------------------------------------------------- */
rast2 raster, band2 integer,
expression text,
pixeltype text DEFAULT NULL, extenttype text DEFAULT 'INTERSECTION',
- nodata1expr text DEFAULT NULL, nodata2expr text DEFAULT NULL, nodatanodataval double precision DEFAULT NULL
+ nodata1expr text DEFAULT NULL, nodata2expr text DEFAULT NULL,
+ nodatanodataval double precision DEFAULT NULL
)
RETURNS raster
- AS 'MODULE_PATHNAME', 'RASTER_mapAlgebra2Expr'
- LANGUAGE 'C' IMMUTABLE;
+ AS 'MODULE_PATHNAME', 'RASTER_mapAlgebra2'
+ LANGUAGE 'C' STABLE;
CREATE OR REPLACE FUNCTION st_mapalgebraexpr(
rast1 raster,
rast2 raster,
expression text,
pixeltype text DEFAULT NULL, extenttype text DEFAULT 'INTERSECTION',
- nodata1expr text DEFAULT NULL, nodata2expr text DEFAULT NULL, nodatanodataval double precision DEFAULT NULL
+ nodata1expr text DEFAULT NULL, nodata2expr text DEFAULT NULL,
+ nodatanodataval double precision DEFAULT NULL
)
RETURNS raster
AS $$ SELECT st_mapalgebraexpr($1, 1, $2, 1, $3, $4, $5, $6, $7, $8) $$
- LANGUAGE 'SQL' IMMUTABLE;
+ LANGUAGE 'SQL' STABLE;
+
+CREATE OR REPLACE FUNCTION st_mapalgebrafct(
+ rast1 raster, band1 integer,
+ rast2 raster, band2 integer,
+ userfunction regprocedure,
+ pixeltype text DEFAULT NULL, extenttype text DEFAULT 'INTERSECTION',
+ VARIADIC userargs text[] DEFAULT NULL
+)
+ RETURNS raster
+ AS 'MODULE_PATHNAME', 'RASTER_mapAlgebra2'
+ LANGUAGE 'C' STABLE;
+
+CREATE OR REPLACE FUNCTION st_mapalgebrafct(
+ rast1 raster,
+ rast2 raster,
+ userfunction regprocedure,
+ pixeltype text DEFAULT NULL, extenttype text DEFAULT 'INTERSECTION',
+ VARIADIC userargs text[] DEFAULT NULL
+)
+ RETURNS raster
+ AS $$ SELECT st_mapalgebrafct($1, 1, $2, 1, $3, $4, $5, VARIADIC $6) $$
+ LANGUAGE 'SQL' STABLE;
+
+CREATE OR REPLACE FUNCTION st_mapalgebrafct(
+ rast1 raster,
+ rast2 raster,
+ userfunction regprocedure,
+ VARIADIC userargs text[]
+)
+ RETURNS raster
+ AS $$ SELECT st_mapalgebrafct($1, 1, $2, 1, $3, NULL, 'INTERSECTION', VARIADIC $4) $$
+ LANGUAGE 'SQL' STABLE;
-----------------------------------------------------------------------
-- Get information about the raster
rt_mapalgebraexpr.sql \
rt_mapalgebrafct.sql \
rt_mapalgebraexpr_2raster.sql \
+ rt_mapalgebrafct_2raster.sql \
rt_reclass.sql \
rt_resample.sql \
rt_asraster.sql \
AND r2.rid BETWEEN 1 AND 9
) UNION ALL (
SELECT r1.rid, r2.rid, 'FIRST', st_mapalgebraexpr(
- r1.rast, r2.rast, '((rast1 + rast2)/2.)::numeric', '32BF', 'UNION', 'rast2', 'rast1', NULL
+ r1.rast, r2.rast, 'CASE WHEN rast2 IS NOT NULL THEN NULL ELSE rast1 END', '32BF', 'FIRST', NULL, 'rast1', NULL
)
FROM raster_mapalgebra r1
JOIN raster_mapalgebra r2
INSERT INTO raster_mapalgebra_out
SELECT NULL AS rid, rid, 'FIRST', st_mapalgebraexpr(
- NULL::raster, rast, 'CASE WHEN rast1 IS NOT NULL THEN NULL ELSE rast2 END', '32BF', 'SECOND', 'rast2', NULL, NULL
+ NULL::raster, rast, 'CASE WHEN rast1 IS NOT NULL THEN NULL ELSE rast2 END', '32BF', 'FIRST', 'rast2', NULL, NULL
)
FROM raster_mapalgebra
;
NOTICE: The two rasters provided have no intersection. Returning no band raster
NOTICE: The two rasters provided are NULL. Returning NULL
NOTICE: The two rasters provided are NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
NOTICE: The two rasters provided are NULL. Returning NULL
NOTICE: The SECOND raster is NULL. Returning NULL
NOTICE: The SECOND raster is NULL. Returning NULL
0|4|FIRST|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
10|11|FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
10|12|FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
-10|13|FIRST|-2.000|-2.000|4|5|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|
-10|14|FIRST|-2.000|-2.000|4|6|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|
-|0|FIRST|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
-|1|FIRST|0.000|0.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|2.000|2.000
-|2|FIRST|1.000|-1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|3.000|3.000
-|3|FIRST|1.000|1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|4.000|4.000
-|4|FIRST|2.000|2.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|5.000|5.000
-|10|FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
-|11|FIRST|0.000|0.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|2.000|2.000
-|12|FIRST|1.000|-1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|3.000|3.000
-|13|FIRST|1.000|1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|4.000|4.000
-|14|FIRST|2.000|2.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|5.000|5.000
+10|13|FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+10|14|FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+|0|FIRST|||||||||||||||
+|1|FIRST|||||||||||||||
+|2|FIRST|||||||||||||||
+|3|FIRST|||||||||||||||
+|4|FIRST|||||||||||||||
+|10|FIRST|||||||||||||||
+|11|FIRST|||||||||||||||
+|12|FIRST|||||||||||||||
+|13|FIRST|||||||||||||||
+|14|FIRST|||||||||||||||
0||FIRST|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
1||FIRST|0.000|0.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|2.000|2.000
2||FIRST|1.000|-1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|3.000|3.000
--- /dev/null
+DROP TABLE IF EXISTS raster_mapalgebra;
+CREATE TABLE raster_mapalgebra (
+ rid integer,
+ rast raster
+);
+DROP TABLE IF EXISTS raster_mapalgebra_out;
+CREATE TABLE raster_mapalgebra_out (
+ rid1 integer,
+ rid2 integer,
+ extent varchar,
+ rast raster
+);
+CREATE OR REPLACE FUNCTION make_test_raster(
+ rid integer,
+ width integer DEFAULT 2,
+ height integer DEFAULT 2,
+ ul_x double precision DEFAULT 0,
+ ul_y double precision DEFAULT 0,
+ skew_x double precision DEFAULT 0,
+ skew_y double precision DEFAULT 0,
+ initvalue double precision DEFAULT 1,
+ nodataval double precision DEFAULT 0
+)
+ RETURNS void
+ AS $$
+ DECLARE
+ x int;
+ y int;
+ rast raster;
+ BEGIN
+ rast := ST_MakeEmptyRaster(width, height, ul_x, ul_y, 1, 1, skew_x, skew_y, 0);
+ rast := ST_AddBand(rast, 1, '8BUI', initvalue, nodataval);
+
+ INSERT INTO raster_mapalgebra VALUES (rid, rast);
+
+ RETURN;
+ END;
+ $$ LANGUAGE 'plpgsql';
+-- no skew
+SELECT make_test_raster(0, 4, 4, -2, -2);
+SELECT make_test_raster(1, 2, 2, 0, 0, 0, 0, 2);
+SELECT make_test_raster(2, 2, 2, 1, -1, 0, 0, 3);
+SELECT make_test_raster(3, 2, 2, 1, 1, 0, 0, 4);
+SELECT make_test_raster(4, 2, 2, 2, 2, 0, 0, 5);
+
+-- skew
+SELECT make_test_raster(10, 4, 4, -2, -2, 1, -1);
+SELECT make_test_raster(11, 2, 2, 0, 0, 1, -1, 2);
+SELECT make_test_raster(12, 2, 2, 1, -1, 1, -1, 3);
+SELECT make_test_raster(13, 2, 2, 1, 1, 1, -1, 4);
+SELECT make_test_raster(14, 2, 2, 2, 2, 1, -1, 5);
+
+DROP FUNCTION IF EXISTS make_test_raster(integer, integer, integer, double precision, double precision, double precision, double precision, double precision, double precision);
+
+CREATE OR REPLACE FUNCTION raster_mapalgebra_intersection(
+ rast1 double precision,
+ rast2 double precision,
+ VARIADIC userargs text[]
+)
+ RETURNS double precision
+ AS $$
+ DECLARE
+ BEGIN
+ IF rast1 IS NOT NULL AND rast2 IS NOT NULL THEN
+ RETURN rast1;
+ ELSE
+ RETURN NULL;
+ END IF;
+
+ RETURN NULL;
+ END;
+ $$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION raster_mapalgebra_union(
+ rast1 double precision,
+ rast2 double precision,
+ VARIADIC userargs text[]
+)
+ RETURNS double precision
+ AS $$
+ DECLARE
+ BEGIN
+ CASE
+ WHEN rast1 IS NOT NULL AND rast2 IS NOT NULL THEN
+ RETURN ((rast1 + rast2)/2.);
+ WHEN rast1 IS NULL AND rast2 IS NULL THEN
+ RETURN NULL;
+ WHEN rast1 IS NULL THEN
+ RETURN rast2;
+ ELSE
+ RETURN rast1;
+ END CASE;
+
+ RETURN NULL;
+ END;
+ $$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION raster_mapalgebra_first(
+ rast1 double precision,
+ rast2 double precision,
+ VARIADIC userargs text[]
+)
+ RETURNS double precision
+ AS $$
+ DECLARE
+ BEGIN
+ CASE
+ WHEN rast1 IS NOT NULL AND rast2 IS NOT NULL THEN
+ RETURN NULL;
+ WHEN rast1 IS NOT NULL THEN
+ RETURN rast1;
+ ELSE
+ RETURN NULL;
+ END CASE;
+
+ RETURN NULL;
+ END;
+ $$ LANGUAGE 'plpgsql';
+
+CREATE OR REPLACE FUNCTION raster_mapalgebra_second(
+ rast1 double precision,
+ rast2 double precision,
+ VARIADIC userargs text[]
+)
+ RETURNS double precision
+ AS $$
+ DECLARE
+ BEGIN
+ CASE
+ WHEN rast1 IS NOT NULL AND rast2 IS NOT NULL THEN
+ RETURN NULL;
+ WHEN rast2 IS NOT NULL THEN
+ RETURN rast2;
+ ELSE
+ RETURN NULL;
+ END CASE;
+
+ RETURN NULL;
+ END;
+ $$ LANGUAGE 'plpgsql';
+
+-- INTERSECTION
+INSERT INTO raster_mapalgebra_out
+ (SELECT r1.rid, r2.rid, 'INTERSECTION', st_mapalgebrafct(
+ r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+ )
+ FROM raster_mapalgebra r1
+ JOIN raster_mapalgebra r2
+ ON r1.rid != r2.rid
+ WHERE r1.rid = 0
+ AND r2.rid BETWEEN 1 AND 9
+ ) UNION ALL (
+ SELECT r1.rid, r2.rid, 'INTERSECTION', st_mapalgebrafct(
+ r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+ )
+ FROM raster_mapalgebra r1
+ JOIN raster_mapalgebra r2
+ ON r1.rid != r2.rid
+ WHERE r1.rid = 10
+ AND r2.rid BETWEEN 11 AND 19)
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT NULL AS rid, rid, 'INTERSECTION', st_mapalgebrafct(
+ NULL::raster, rast, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+ )
+ FROM raster_mapalgebra
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT rid, NULL AS rid, 'INTERSECTION', st_mapalgebrafct(
+ rast, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+ )
+ FROM raster_mapalgebra
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT NULL AS rid, NULL AS rid, 'INTERSECTION', st_mapalgebrafct(
+ NULL::raster, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+ )
+;
+
+-- UNION
+INSERT INTO raster_mapalgebra_out
+ (SELECT r1.rid, r2.rid, 'UNION', st_mapalgebrafct(
+ r1.rast, r2.rast, 'raster_mapalgebra_union(double precision, double precision, text[])'::regprocedure, '32BF', 'UNION'
+ )
+ FROM raster_mapalgebra r1
+ JOIN raster_mapalgebra r2
+ ON r1.rid != r2.rid
+ WHERE r1.rid = 0
+ AND r2.rid BETWEEN 1 AND 9
+ ) UNION ALL (
+ SELECT r1.rid, r2.rid, 'UNION', st_mapalgebrafct(
+ r1.rast, r2.rast, 'raster_mapalgebra_union(double precision, double precision, text[])'::regprocedure, '32BF', 'UNION'
+ )
+ FROM raster_mapalgebra r1
+ JOIN raster_mapalgebra r2
+ ON r1.rid != r2.rid
+ WHERE r1.rid = 10
+ AND r2.rid BETWEEN 11 AND 19)
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT NULL AS rid, rid, 'UNION', st_mapalgebrafct(
+ NULL::raster, rast, 'raster_mapalgebra_union(double precision, double precision, text[])'::regprocedure, '32BF', 'UNION'
+ )
+ FROM raster_mapalgebra
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT rid, NULL AS rid, 'UNION', st_mapalgebrafct(
+ rast, NULL::raster, 'raster_mapalgebra_union(double precision, double precision, text[])'::regprocedure, '32BF', 'UNION'
+ )
+ FROM raster_mapalgebra
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT NULL AS rid, NULL AS rid, 'UNION', st_mapalgebrafct(
+ NULL::raster, NULL::raster, 'raster_mapalgebra_union(double precision, double precision, text[])'::regprocedure, '32BF', 'UNION'
+ )
+;
+
+-- FIRST
+INSERT INTO raster_mapalgebra_out
+ (SELECT r1.rid, r2.rid, 'FIRST', st_mapalgebrafct(
+ r1.rast, r2.rast, 'raster_mapalgebra_first(double precision, double precision, text[])'::regprocedure, '32BF', 'FIRST'
+ )
+ FROM raster_mapalgebra r1
+ JOIN raster_mapalgebra r2
+ ON r1.rid != r2.rid
+ WHERE r1.rid = 0
+ AND r2.rid BETWEEN 1 AND 9
+ ) UNION ALL (
+ SELECT r1.rid, r2.rid, 'FIRST', st_mapalgebrafct(
+ r1.rast, r2.rast, 'raster_mapalgebra_first(double precision, double precision, text[])'::regprocedure, '32BF', 'FIRST'
+ )
+ FROM raster_mapalgebra r1
+ JOIN raster_mapalgebra r2
+ ON r1.rid != r2.rid
+ WHERE r1.rid = 10
+ AND r2.rid BETWEEN 11 AND 19)
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT NULL AS rid, rid, 'FIRST', st_mapalgebrafct(
+ NULL::raster, rast, 'raster_mapalgebra_first(double precision, double precision, text[])'::regprocedure, '32BF', 'FIRST'
+ )
+ FROM raster_mapalgebra
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT rid, NULL AS rid, 'FIRST', st_mapalgebrafct(
+ rast, NULL::raster, 'raster_mapalgebra_first(double precision, double precision, text[])'::regprocedure, '32BF', 'FIRST'
+ )
+ FROM raster_mapalgebra
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT NULL AS rid, NULL AS rid, 'FIRST', st_mapalgebrafct(
+ NULL::raster, NULL::raster, 'raster_mapalgebra_first(double precision, double precision, text[])'::regprocedure, '32BF', 'FIRST'
+ )
+;
+
+-- SECOND
+INSERT INTO raster_mapalgebra_out
+ (SELECT r1.rid, r2.rid, 'SECOND', st_mapalgebrafct(
+ r1.rast, r2.rast, 'raster_mapalgebra_second(double precision, double precision, text[])'::regprocedure, '32BF', 'SECOND'
+ )
+ FROM raster_mapalgebra r1
+ JOIN raster_mapalgebra r2
+ ON r1.rid != r2.rid
+ WHERE r1.rid = 0
+ AND r2.rid BETWEEN 1 AND 9
+ ) UNION ALL (
+ SELECT r1.rid, r2.rid, 'SECOND', st_mapalgebrafct(
+ r1.rast, r2.rast, 'raster_mapalgebra_second(double precision, double precision, text[])'::regprocedure, '32BF', 'SECOND'
+ )
+ FROM raster_mapalgebra r1
+ JOIN raster_mapalgebra r2
+ ON r1.rid != r2.rid
+ WHERE r1.rid = 10
+ AND r2.rid BETWEEN 11 AND 19)
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT NULL AS rid, rid, 'SECOND', st_mapalgebrafct(
+ NULL::raster, rast, 'raster_mapalgebra_second(double precision, double precision, text[])'::regprocedure, '32BF', 'SECOND'
+ )
+ FROM raster_mapalgebra
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT rid, NULL AS rid, 'SECOND', st_mapalgebrafct(
+ rast, NULL::raster, 'raster_mapalgebra_second(double precision, double precision, text[])'::regprocedure, '32BF', 'SECOND'
+ )
+ FROM raster_mapalgebra
+;
+
+INSERT INTO raster_mapalgebra_out
+ SELECT NULL AS rid, NULL AS rid, 'SECOND', st_mapalgebrafct(
+ NULL::raster, NULL::raster, 'raster_mapalgebra_second(double precision, double precision, text[])'::regprocedure, '32BF', 'SECOND'
+ )
+;
+
+-- output
+SELECT
+ rid1,
+ rid2,
+ extent,
+ round(upperleftx::numeric, 3) AS upperleftx,
+ round(upperlefty::numeric, 3) AS upperlefty,
+ width,
+ height,
+ round(scalex::numeric, 3) AS scalex,
+ round(scaley::numeric, 3) AS scaley,
+ round(skewx::numeric, 3) AS skewx,
+ round(skewy::numeric, 3) AS skewy,
+ srid,
+ numbands,
+ pixeltype,
+ hasnodata,
+ round(nodatavalue::numeric, 3) AS nodatavalue,
+ round(firstvalue::numeric, 3) AS firstvalue,
+ round(lastvalue::numeric, 3) AS lastvalue
+FROM (
+ SELECT
+ rid1,
+ rid2,
+ extent,
+ (ST_Metadata(rast)).*,
+ (ST_BandMetadata(rast, 1)).*,
+ ST_Value(rast, 1, 1, 1) AS firstvalue,
+ ST_Value(rast, 1, ST_Width(rast), ST_Height(rast)) AS lastvalue
+ FROM raster_mapalgebra_out
+) AS r;
+
+DROP FUNCTION IF EXISTS raster_mapalgebra_intersection(double precision, double precision, VARIADIC text[]);
+DROP FUNCTION IF EXISTS raster_mapalgebra_union(double precision, double precision, VARIADIC text[]);
+DROP FUNCTION IF EXISTS raster_mapalgebra_first(double precision, double precision, VARIADIC text[]);
+DROP FUNCTION IF EXISTS raster_mapalgebra_second(double precision, double precision, VARIADIC text[]);
+
+DROP TABLE IF EXISTS raster_mapalgebra;
+DROP TABLE IF EXISTS raster_mapalgebra_out;
--- /dev/null
+NOTICE: table "raster_mapalgebra" does not exist, skipping
+NOTICE: table "raster_mapalgebra_out" does not exist, skipping
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided have no intersection. Returning no band raster
+NOTICE: The two rasters provided are NULL. Returning NULL
+NOTICE: The two rasters provided are NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The FIRST raster is NULL. Returning NULL
+NOTICE: The two rasters provided are NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The SECOND raster is NULL. Returning NULL
+NOTICE: The two rasters provided are NULL. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Raster provided has no bands
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+NOTICE: Could not find raster band of index 1 when getting pixel value. Returning NULL
+0|1|INTERSECTION|0.000|0.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
+0|2|INTERSECTION|1.000|-1.000|1|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
+0|3|INTERSECTION|1.000|1.000|1|1|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
+0|4|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+10|11|INTERSECTION|0.000|0.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+10|12|INTERSECTION|1.000|-1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+10|13|INTERSECTION|1.000|1.000|2|1|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+10|14|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|0|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|1|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|2|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|3|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|4|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|10|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|11|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|12|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|13|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+|14|INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+0||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+1||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+2||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+3||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+4||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+10||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+11||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+12||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+13||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+14||INTERSECTION|0.000|0.000|0|0|0.000|0.000|0.000|0.000|0|0|||||
+||INTERSECTION|||||||||||||||
+0|1|UNION|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.500
+0|2|UNION|-2.000|-2.000|5|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|
+0|3|UNION|-2.000|-2.000|5|5|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|4.000
+0|4|UNION|-2.000|-2.000|6|6|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|5.000
+10|11|UNION|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+10|12|UNION|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+10|13|UNION|-2.000|-2.000|4|5|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|
+10|14|UNION|-2.000|-2.000|4|6|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|
+|0|UNION|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
+|1|UNION|0.000|0.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|2.000|2.000
+|2|UNION|1.000|-1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|3.000|3.000
+|3|UNION|1.000|1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|4.000|4.000
+|4|UNION|2.000|2.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|5.000|5.000
+|10|UNION|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+|11|UNION|0.000|0.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|2.000|2.000
+|12|UNION|1.000|-1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|3.000|3.000
+|13|UNION|1.000|1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|4.000|4.000
+|14|UNION|2.000|2.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|5.000|5.000
+0||UNION|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
+1||UNION|0.000|0.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|2.000|2.000
+2||UNION|1.000|-1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|3.000|3.000
+3||UNION|1.000|1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|4.000|4.000
+4||UNION|2.000|2.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|5.000|5.000
+10||UNION|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+11||UNION|0.000|0.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|2.000|2.000
+12||UNION|1.000|-1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|3.000|3.000
+13||UNION|1.000|1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|4.000|4.000
+14||UNION|2.000|2.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|5.000|5.000
+||UNION|||||||||||||||
+0|1|FIRST|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|
+0|2|FIRST|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
+0|3|FIRST|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|
+0|4|FIRST|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
+10|11|FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+10|12|FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+10|13|FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+10|14|FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+|0|FIRST|||||||||||||||
+|1|FIRST|||||||||||||||
+|2|FIRST|||||||||||||||
+|3|FIRST|||||||||||||||
+|4|FIRST|||||||||||||||
+|10|FIRST|||||||||||||||
+|11|FIRST|||||||||||||||
+|12|FIRST|||||||||||||||
+|13|FIRST|||||||||||||||
+|14|FIRST|||||||||||||||
+0||FIRST|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
+1||FIRST|0.000|0.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|2.000|2.000
+2||FIRST|1.000|-1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|3.000|3.000
+3||FIRST|1.000|1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|4.000|4.000
+4||FIRST|2.000|2.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|5.000|5.000
+10||FIRST|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+11||FIRST|0.000|0.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|2.000|2.000
+12||FIRST|1.000|-1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|3.000|3.000
+13||FIRST|1.000|1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|4.000|4.000
+14||FIRST|2.000|2.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|5.000|5.000
+||FIRST|||||||||||||||
+0|1|SECOND|0.000|0.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000||
+0|2|SECOND|1.000|-1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000||3.000
+0|3|SECOND|1.000|1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000||4.000
+0|4|SECOND|2.000|2.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|5.000|5.000
+10|11|SECOND|0.000|0.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000||
+10|12|SECOND|1.000|-1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000||
+10|13|SECOND|1.000|1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000||4.000
+10|14|SECOND|2.000|2.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|5.000|5.000
+|0|SECOND|-2.000|-2.000|4|4|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|1.000|1.000
+|1|SECOND|0.000|0.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|2.000|2.000
+|2|SECOND|1.000|-1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|3.000|3.000
+|3|SECOND|1.000|1.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|4.000|4.000
+|4|SECOND|2.000|2.000|2|2|1.000|1.000|0.000|0.000|0|1|32BF|t|0.000|5.000|5.000
+|10|SECOND|-2.000|-2.000|4|4|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|1.000|1.000
+|11|SECOND|0.000|0.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|2.000|2.000
+|12|SECOND|1.000|-1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|3.000|3.000
+|13|SECOND|1.000|1.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|4.000|4.000
+|14|SECOND|2.000|2.000|2|2|1.000|1.000|1.000|-1.000|0|1|32BF|t|0.000|5.000|5.000
+0||SECOND|||||||||||||||
+1||SECOND|||||||||||||||
+2||SECOND|||||||||||||||
+3||SECOND|||||||||||||||
+4||SECOND|||||||||||||||
+10||SECOND|||||||||||||||
+11||SECOND|||||||||||||||
+12||SECOND|||||||||||||||
+13||SECOND|||||||||||||||
+14||SECOND|||||||||||||||
+||SECOND|||||||||||||||