PostGIS  2.5.0dev-r@@SVN_REVISION@@

◆ rt_band_get_nearest_pixel()

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.

Parameters
band: the band to get nearest pixel(s) from
x: the column of the pixel (0-based)
y: the line of the pixel (0-based)
distancex: the number of pixels around the specified pixel along the X axis
distancey: the number of pixels around the specified pixel along the Y axis
exclude_nodata_value: if non-zero, ignore nodata values to check for pixels with value
npixels: return set of rt_pixel object or NULL
Returns
-1 on error, otherwise the number of rt_pixel objects in npixels

Definition at line 1326 of file rt_band.c.

References genraster::count, distance(), ES_NONE, FALSE, rt_band_t::hasnodata, rt_band_t::height, rt_band_t::isnodata, rt_pixel_t::nodata, rt_band_t::nodataval, rt_band_t::pixtype, pixval::pixval, RASTER_DEBUG, RASTER_DEBUGF, rt_band_get_pixel(), rt_pixtype_get_min_value(), rt_pixtype_name(), rtalloc(), rtdealloc(), rterror(), rtrealloc(), rt_pixel_t::value, rt_band_t::width, rt_pixel_t::x, and rt_pixel_t::y.

Referenced by RASTER_nearestValue(), RASTER_neighborhood(), rt_raster_iterator(), test_band_get_nearest_pixel(), and test_pixel_set_to_array().

1332  {
1333  rt_pixel npixel = NULL;
1334  int extent[4] = {0};
1335  int max_extent[4] = {0};
1336  int d0 = 0;
1337  uint32_t distance[2] = {0};
1338  uint32_t _d[2] = {0};
1339  uint32_t i = 0;
1340  uint32_t j = 0;
1341  uint32_t k = 0;
1342  int _max = 0;
1343  int _x = 0;
1344  int _y = 0;
1345  int *_min = NULL;
1346  double pixval = 0;
1347  double minval = 0;
1348  uint32_t count = 0;
1349  int isnodata = 0;
1350 
1351  int inextent = 0;
1352 
1353  assert(NULL != band);
1354  assert(NULL != npixels);
1355 
1356  RASTER_DEBUG(3, "Starting");
1357 
1358  /* process distance */
1359  distance[0] = distancex;
1360  distance[1] = distancey;
1361 
1362  /* no distance, means get nearest pixels and return */
1363  if (!distance[0] && !distance[1])
1364  d0 = 1;
1365 
1366  RASTER_DEBUGF(4, "Selected pixel: %d x %d", x, y);
1367  RASTER_DEBUGF(4, "Distances: %d x %d", distance[0], distance[1]);
1368 
1369  /* shortcuts if outside band extent */
1370  if (
1371  exclude_nodata_value && (
1372  (x < 0 || x > band->width) ||
1373  (y < 0 || y > band->height)
1374  )
1375  ) {
1376  /* no distances specified, jump to pixel close to extent */
1377  if (d0) {
1378  if (x < 0)
1379  x = -1;
1380  else if (x > band->width)
1381  x = band->width;
1382 
1383  if (y < 0)
1384  y = -1;
1385  else if (y > band->height)
1386  y = band->height;
1387 
1388  RASTER_DEBUGF(4, "Moved selected pixel: %d x %d", x, y);
1389  }
1390  /*
1391  distances specified
1392  if distances won't capture extent of band, return 0
1393  */
1394  else if (
1395  ((x < 0 && (uint32_t) abs(x) > distance[0]) || (x - band->width >= (int)distance[0])) ||
1396  ((y < 0 && (uint32_t) abs(y) > distance[1]) || (y - band->height >= (int)distance[1]))
1397  ) {
1398  RASTER_DEBUG(4, "No nearest pixels possible for provided pixel and distances");
1399  return 0;
1400  }
1401  }
1402 
1403  /* no NODATA, exclude is FALSE */
1404  if (!band->hasnodata)
1405  exclude_nodata_value = FALSE;
1406  /* band is NODATA and excluding NODATA */
1407  else if (exclude_nodata_value && band->isnodata) {
1408  RASTER_DEBUG(4, "No nearest pixels possible as band is NODATA and excluding NODATA values");
1409  return 0;
1410  }
1411 
1412  /* determine the maximum distance to prevent an infinite loop */
1413  if (d0) {
1414  int a, b;
1415 
1416  /* X axis */
1417  a = abs(x);
1418  b = abs(x - band->width);
1419 
1420  if (a > b)
1421  distance[0] = a;
1422  else
1423  distance[0] = b;
1424 
1425  /* Y axis */
1426  a = abs(y);
1427  b = abs(y - band->height);
1428  if (a > b)
1429  distance[1] = a;
1430  else
1431  distance[1] = b;
1432 
1433  RASTER_DEBUGF(4, "Maximum distances: %d x %d", distance[0], distance[1]);
1434  }
1435 
1436  /* minimum possible value for pixel type */
1437  minval = rt_pixtype_get_min_value(band->pixtype);
1438  RASTER_DEBUGF(4, "pixtype: %s", rt_pixtype_name(band->pixtype));
1439  RASTER_DEBUGF(4, "minval: %f", minval);
1440 
1441  /* set variables */
1442  count = 0;
1443  *npixels = NULL;
1444 
1445  /* maximum extent */
1446  max_extent[0] = x - distance[0]; /* min X */
1447  max_extent[1] = y - distance[1]; /* min Y */
1448  max_extent[2] = x + distance[0]; /* max X */
1449  max_extent[3] = y + distance[1]; /* max Y */
1450  RASTER_DEBUGF(4, "Maximum Extent: (%d, %d, %d, %d)",
1451  max_extent[0], max_extent[1], max_extent[2], max_extent[3]);
1452 
1453  _d[0] = 0;
1454  _d[1] = 0;
1455  do {
1456  _d[0]++;
1457  _d[1]++;
1458 
1459  extent[0] = x - _d[0]; /* min x */
1460  extent[1] = y - _d[1]; /* min y */
1461  extent[2] = x + _d[0]; /* max x */
1462  extent[3] = y + _d[1]; /* max y */
1463 
1464  RASTER_DEBUGF(4, "Processing distances: %d x %d", _d[0], _d[1]);
1465  RASTER_DEBUGF(4, "Extent: (%d, %d, %d, %d)",
1466  extent[0], extent[1], extent[2], extent[3]);
1467 
1468  for (i = 0; i < 2; i++) {
1469 
1470  /* by row */
1471  if (i < 1)
1472  _max = extent[2] - extent[0] + 1;
1473  /* by column */
1474  else
1475  _max = extent[3] - extent[1] + 1;
1476  _max = abs(_max);
1477 
1478  for (j = 0; j < 2; j++) {
1479  /* by row */
1480  if (i < 1) {
1481  _x = extent[0];
1482  _min = &_x;
1483 
1484  /* top row */
1485  if (j < 1)
1486  _y = extent[1];
1487  /* bottom row */
1488  else
1489  _y = extent[3];
1490  }
1491  /* by column */
1492  else {
1493  _y = extent[1] + 1;
1494  _min = &_y;
1495 
1496  /* left column */
1497  if (j < 1) {
1498  _x = extent[0];
1499  _max -= 2;
1500  }
1501  /* right column */
1502  else
1503  _x = extent[2];
1504  }
1505 
1506  RASTER_DEBUGF(4, "_min, _max: %d, %d", *_min, _max);
1507  for (k = 0; k < (uint32_t) _max; k++) {
1508  /* check that _x and _y are not outside max extent */
1509  if (
1510  _x < max_extent[0] || _x > max_extent[2] ||
1511  _y < max_extent[1] || _y > max_extent[3]
1512  ) {
1513  (*_min)++;
1514  continue;
1515  }
1516 
1517  /* outside band extent, set to NODATA */
1518  if (
1519  (_x < 0 || _x >= band->width) ||
1520  (_y < 0 || _y >= band->height)
1521  ) {
1522  /* no NODATA, set to minimum possible value */
1523  if (!band->hasnodata)
1524  pixval = minval;
1525  /* has NODATA, use NODATA */
1526  else
1527  pixval = band->nodataval;
1528  RASTER_DEBUGF(4, "NODATA pixel outside band extent: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1529  inextent = 0;
1530  isnodata = 1;
1531  }
1532  else {
1533  if (rt_band_get_pixel(
1534  band,
1535  _x, _y,
1536  &pixval,
1537  &isnodata
1538  ) != ES_NONE) {
1539  rterror("rt_band_get_nearest_pixel: Could not get pixel value");
1540  if (count) rtdealloc(*npixels);
1541  return -1;
1542  }
1543  RASTER_DEBUGF(4, "Pixel: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1544  inextent = 1;
1545  }
1546 
1547  /* use pixval? */
1548  if (!exclude_nodata_value || (exclude_nodata_value && !isnodata)) {
1549  /* add pixel to result set */
1550  RASTER_DEBUGF(4, "Adding pixel to set of nearest pixels: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1551  count++;
1552 
1553  if (*npixels == NULL)
1554  *npixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t) * count);
1555  else
1556  *npixels = (rt_pixel) rtrealloc(*npixels, sizeof(struct rt_pixel_t) * count);
1557  if (*npixels == NULL) {
1558  rterror("rt_band_get_nearest_pixel: Could not allocate memory for nearest pixel(s)");
1559  return -1;
1560  }
1561 
1562  npixel = &((*npixels)[count - 1]);
1563  npixel->x = _x;
1564  npixel->y = _y;
1565  npixel->value = pixval;
1566 
1567  /* special case for when outside band extent */
1568  if (!inextent && !band->hasnodata)
1569  npixel->nodata = 1;
1570  else
1571  npixel->nodata = 0;
1572  }
1573 
1574  (*_min)++;
1575  }
1576  }
1577  }
1578 
1579  /* distance threshholds met */
1580  if (_d[0] >= distance[0] && _d[1] >= distance[1])
1581  break;
1582  else if (d0 && count)
1583  break;
1584  }
1585  while (1);
1586 
1587  RASTER_DEBUGF(3, "Nearest pixels in return: %d", count);
1588 
1589  return count;
1590 }
struct rt_pixel_t * rt_pixel
Definition: librtcore.h:147
rt_pixtype pixtype
Definition: librtcore.h:2294
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition: rt_context.c:199
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition: rt_context.c:171
void * rtrealloc(void *mem, size_t size)
Definition: rt_context.c:179
uint16_t height
Definition: librtcore.h:2297
double value
Definition: librtcore.h:2318
unsigned int uint32_t
Definition: uthash.h:78
Definition: pixval.py:1
int count
Definition: genraster.py:56
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1173
double nodataval
Definition: librtcore.h:2301
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_pixel.c:148
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:299
uint8_t nodata
Definition: librtcore.h:2317
uint16_t width
Definition: librtcore.h:2296
Datum distance(PG_FUNCTION_ARGS)
pixval
Definition: pixval.py:93
void rtdealloc(void *mem)
Definition: rt_context.c:186
int32_t isnodata
Definition: librtcore.h:2299
#define FALSE
Definition: dbfopen.c:168
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:295
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
int32_t hasnodata
Definition: librtcore.h:2298
Here is the call graph for this function:
Here is the caller graph for this function: