n-raster iterator.
827 {
828
830
832
833
835
837 int allnull = 0;
838 int allempty = 0;
839 int aligned = 0;
840 double offset[4] = {0.};
842
843 int i = 0;
844 int status = 0;
845 int inextent = 0;
848 int _x = 0;
849 int _y = 0;
850
851 int _width = 0;
852 int _height = 0;
853
854 double minval;
856 int isnodata;
857 int nodata;
858
860
861 assert(itrset != NULL && itrcount > 0);
862 assert(rtnraster != NULL);
863
864
865 *rtnraster = NULL;
866
867
868 if (callback == NULL) {
869 rterror(
"rt_raster_iterator: Callback function not provided");
871 }
872
873
875 rterror(
"rt_raster_iterator: Custom extent cannot be empty if extent type is ET_CUSTOM");
877 }
878
879
881 rterror(
"rt_raster_iterator: Pixel type cannot be PT_END");
883 }
884
885
887 rterror(
"rt_raster_iterator: Could not initialize internal variables");
889 }
890
891
893 rterror(
"rt_raster_iterator: Could not populate for internal variables");
896 }
897
898
899 if (allnull == itrcount) {
900 RASTER_DEBUG(3,
"all rasters are NULL, returning NULL");
901
903
905 }
906
907 else if (allempty == itrcount) {
908 RASTER_DEBUG(3,
"all rasters are empty, returning empty raster");
909
911
913 if (rtnrast == NULL) {
914 rterror(
"rt_raster_iterator: Could not create empty raster");
916 }
918
919 *rtnraster = rtnrast;
921 }
922
923
926
927
928
930 RASTER_DEBUG(4,
"using custom extent as reference raster");
932 }
933
934 else {
935 for (i = 0; i < itrcount; i++) {
937 RASTER_DEBUGF(4,
"using raster at index %d as reference raster", i);
939 break;
940 }
941 }
942 }
943
944
945 if (rast == NULL) {
946 rterror(
"rt_raster_iterator: Could not find reference raster to use for alignment tests");
947
949
951 }
952
953 do {
954 aligned = 1;
955
956
957 if (extenttype ==
ET_CUSTOM && rast != customextent) {
959 rterror(
"rt_raster_iterator: Could not test for alignment between reference raster and custom extent");
960
962
964 }
965
967 if (!aligned)
968 break;
969 }
970
971 for (i = 0; i < itrcount; i++) {
972
974 continue;
975
977 rterror(
"rt_raster_iterator: Could not test for alignment between reference raster and raster %d", i);
978
980
982 }
983 RASTER_DEBUGF(5,
"raster at index %d alignment: %d", i, aligned);
984
985
986 if (!aligned)
987 break;
988 }
989 }
990 while (0);
991
992
993 if (!aligned) {
994 rterror(
"rt_raster_iterator: The set of rasters provided (custom extent included, if appropriate) do not have the same alignment");
995
997
999 }
1000
1001
1002 i = -1;
1003 switch (extenttype) {
1006
1008 if (rtnrast == NULL) {
1009 rterror(
"rt_raster_iterator: Could not allocate memory for output raster");
1010
1012
1014 }
1015
1016 for (i = 0; i < itrcount; i++) {
1019 break;
1020 }
1021 }
1023 rtnrast->
bands = NULL;
1024
1025
1027 for (i = i + 1; i < itrcount; i++) {
1029 continue;
1030
1033
1034 if (rast == NULL || status !=
ES_NONE) {
1035 rterror(
"rt_raster_iterator: Could not compute %s extent of rasters",
1036 extenttype ==
ET_UNION ?
"union" :
"intersection"
1037 );
1038
1040
1042 }
1044 rtinfo(
"rt_raster_iterator: Computed raster for %s extent is empty",
1045 extenttype ==
ET_UNION ?
"union" :
"intersection"
1046 );
1047
1049
1052 }
1053
1056 }
1057
1058 break;
1059
1060
1061
1062
1064 i = 0;
1065
1067 if (i < 0) {
1068 if (itrcount < 2)
1069 i = 0;
1070 else
1071 i = 1;
1072 }
1073
1075 if (i < 0) i = itrcount - 1;
1076
1077
1078 if (_param->
raster[i] == NULL) {
1079 RASTER_DEBUGF(3,
"returning NULL as %s raster is NULL and extent type is ET_%s",
1080 (i == 0 ? "first" : (i == 1 ? "second" : "last")),
1081 (i == 0 ? "FIRST" : (i == 1 ? "SECOND" : "LAST"))
1082 );
1083
1085
1087 }
1088
1089 else if (_param->
isempty[i]) {
1090 RASTER_DEBUGF(3,
"returning empty raster as %s raster is empty and extent type is ET_%s",
1091 (i == 0 ? "first" : (i == 1 ? "second" : "last")),
1092 (i == 0 ? "FIRST" : (i == 1 ? "SECOND" : "LAST"))
1093 );
1094
1096
1098 if (rtnrast == NULL) {
1099 rterror(
"rt_raster_iterator: Could not create empty raster");
1101 }
1103
1104 *rtnraster = rtnrast;
1106 }
1107
1108
1111 if (rtnrast == NULL) {
1112 rterror(
"rt_raster_iterator: Could not allocate memory for output raster");
1113
1115
1117 }
1118
1119 switch (extenttype) {
1121 memcpy(rtnrast, customextent,
sizeof(
struct rt_raster_t));
1122 break;
1123
1124 default:
1126 break;
1127 }
1129 rtnrast->
bands = NULL;
1130 break;
1131 }
1132
1135
1136 RASTER_DEBUGF(4,
"rtnrast (width, height, ulx, uly, scalex, scaley, skewx, skewy, srid) = (%d, %d, %f, %f, %f, %f, %f, %f, %d)",
1137 _width,
1138 _height,
1146 );
1147
1148
1150 rterror(
"rt_raster_iterator: Could not initialize empty values and NODATA");
1151
1154
1156 }
1157
1158
1160 rtnrast,
1161 pixtype,
1162 nodataval,
1163 hasnodata, nodataval,
1164 0
1165 ) < 0) {
1166 rterror(
"rt_raster_iterator: Could not add new band to output raster");
1167
1170
1172 }
1173
1174
1176 if (rtnband == NULL) {
1177 rterror(
"rt_raster_iterator: Could not get new band from output raster");
1178
1181
1183 }
1184
1185
1187
1188
1190 rterror(
"rt_raster_iterator: Could not initialize callback function argument");
1191
1195
1197 }
1198
1199
1200 for (i = 0; i < itrcount; i++) {
1202 continue;
1203
1207 rterror(
"rt_raster_iterator: Could not compute raster offsets");
1208
1212
1214 }
1215
1216 _param->
offset[i][0] = offset[2];
1217 _param->
offset[i][1] = offset[3];
1218 RASTER_DEBUGF(4,
"rast %d offset: %f %f", i, offset[2], offset[3]);
1219 }
1220
1221
1222
1223
1224 for (_y = 0; _y < _height; _y++) {
1225 for (_x = 0; _x < _width; _x++) {
1226 RASTER_DEBUGF(4,
"iterating output pixel (x, y) = (%d, %d)", _x, _y);
1229
1230
1231 for (i = 0; i < itrcount; i++) {
1233
1234
1235
1236
1237
1238
1239 if (
1241 (_param->
band.
rtband[i] == NULL && itrset[i].nbnodata) ||
1243 ) {
1244 RASTER_DEBUG(4,
"empty raster, band does not exist or band is NODATA. using empty values and NODATA");
1245
1248
1251
1252 continue;
1253 }
1254
1255
1256 x = _x - (int) _param->
offset[i][0];
1257 y = _y - (int) _param->
offset[i][1];
1259
1262
1263
1264 npixels = NULL;
1265 status = 0;
1266 if (distancex > 0 && distancey > 0) {
1268
1271 x, y,
1272 distancex, distancey,
1273 1,
1274 &npixels
1275 );
1276 if (status < 0) {
1277 rterror(
"rt_raster_iterator: Could not get pixel neighborhood");
1278
1282
1284 }
1285 }
1286
1287
1288
1289 if (
1290 (x >= 0 && x < _param->width[i]) &&
1291 (y >= 0 && y < _param->height[i])
1292 ) {
1296 x, y,
1297 &value,
1298 &isnodata
1300 rterror(
"rt_raster_iterator: Could not get the pixel value of band");
1301
1305
1307 }
1308 inextent = 1;
1309 }
1310
1311 else {
1312 RASTER_DEBUG(4,
"Outside band extent, setting value to NODATA");
1313
1316
1317 else
1319
1320 inextent = 0;
1321 isnodata = 1;
1322 }
1323
1324
1325 status++;
1326 if (status > 1)
1328 else
1330
1331 if (npixels == NULL) {
1332 rterror(
"rt_raster_iterator: Could not reallocate memory for neighborhood");
1333
1337
1339 }
1340
1341 npixels[status - 1].
x =
x;
1342 npixels[status - 1].
y =
y;
1343 npixels[status - 1].
nodata = 1;
1345
1346
1347 if ((!_param->
band.
hasnodata[i] && inextent) || !isnodata) {
1348 npixels[status - 1].
nodata = 0;
1349 }
1350 RASTER_DEBUGF(4,
"value, nodata: %f, %d", value, npixels[status - 1].nodata);
1351
1352
1354 npixels, status, mask,
1355 x, y,
1356 distancex, distancey,
1359 NULL, NULL
1360 );
1363 rterror(
"rt_raster_iterator: Could not create 2D array of neighborhood");
1364
1368
1370 }
1371 }
1372
1373
1376 nodata = 0;
1377 status = callback(_param->
arg, userarg, &value, &nodata);
1378
1379
1381
1382
1383 if (status == 0) {
1384 rterror(
"rt_raster_iterator: Callback function returned an error");
1385
1389
1391 }
1392
1393
1394 status = 0;
1395 if (!nodata) {
1397 RASTER_DEBUGF(4,
"burning pixel (%d, %d) with value: %f", _x, _y, value);
1398 }
1399 else if (!hasnodata) {
1401 RASTER_DEBUGF(4,
"burning pixel (%d, %d) with minval: %f", _x, _y, minval);
1402 }
1403 else {
1405 }
1407 rterror(
"rt_raster_iterator: Could not set pixel value");
1408
1412
1414 }
1415 }
1416 }
1417
1418
1420
1421 *rtnraster = rtnrast;
1423}
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
#define RASTER_DEBUG(level, msg)
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
#define RASTER_DEBUGF(level, msg,...)
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
int rt_raster_generate_new_band(rt_raster raster, rt_pixtype pixtype, double initialvalue, uint32_t hasnodata, double nodatavalue, int index)
Generate a new inline band and add it to a raster.
void rtinfo(const char *fmt,...)
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
struct rt_pixel_t * rt_pixel
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel's value.
void rt_band_destroy(rt_band band)
Destroy a raster band.
void * rtrealloc(void *mem, size_t size)
uint16_t rt_raster_get_height(rt_raster raster)
rt_errorstate rt_pixel_set_to_array(rt_pixel npixel, uint32_t count, rt_mask mask, int x, int y, uint16_t distancex, uint16_t distancey, double ***value, int ***nodata, int *dimx, int *dimy)
uint16_t rt_raster_get_width(rt_raster raster)
uint32_t rt_band_get_nearest_pixel(rt_band band, int x, int y, uint16_t distancex, uint16_t distancey, int exclude_nodata_value, rt_pixel *npixels)
Get nearest pixel(s) with value (not NODATA) to specified pixel.
void rtdealloc(void *mem)
rt_errorstate rt_raster_from_two_rasters(rt_raster rast1, rt_raster rast2, rt_extenttype extenttype, rt_raster *rtnraster, double *offset)
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
static int _rti_iterator_arg_callback_init(_rti_iterator_arg _param)
static int _rti_iterator_arg_empty_init(_rti_iterator_arg _param)
static _rti_iterator_arg _rti_iterator_arg_init()
static int _rti_iterator_arg_populate(_rti_iterator_arg _param, rt_iterator itrset, uint16_t itrcount, uint16_t distancex, uint16_t distancey, int *allnull, int *allempty)
static void _rti_iterator_arg_callback_clean(_rti_iterator_arg _param)
static void _rti_iterator_arg_destroy(_rti_iterator_arg _param)
struct _rti_iterator_arg_t::@10 band
struct _rti_iterator_arg_t::@13 empty