PostGIS  3.4.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 1529 of file rt_band.c.

1535  {
1536  rt_pixel npixel = NULL;
1537  int extent[4] = {0};
1538  int max_extent[4] = {0};
1539  int d0 = 0;
1540  uint32_t distance[2] = {0};
1541  uint32_t _d[2] = {0};
1542  uint32_t i = 0;
1543  uint32_t j = 0;
1544  uint32_t k = 0;
1545  int _max = 0;
1546  int _x = 0;
1547  int _y = 0;
1548  int *_min = NULL;
1549  double pixval = 0;
1550  double minval = 0;
1551  uint32_t count = 0;
1552  int isnodata = 0;
1553 
1554  int inextent = 0;
1555 
1556  assert(NULL != band);
1557  assert(NULL != npixels);
1558 
1559  RASTER_DEBUG(3, "Starting");
1560 
1561  /* process distance */
1562  distance[0] = distancex;
1563  distance[1] = distancey;
1564 
1565  /* no distance, means get nearest pixels and return */
1566  if (!distance[0] && !distance[1])
1567  d0 = 1;
1568 
1569  RASTER_DEBUGF(4, "Selected pixel: %d x %d", x, y);
1570  RASTER_DEBUGF(4, "Distances: %d x %d", distance[0], distance[1]);
1571 
1572  /* shortcuts if outside band extent */
1573  if (
1574  exclude_nodata_value && (
1575  (x < 0 || x > band->width) ||
1576  (y < 0 || y > band->height)
1577  )
1578  ) {
1579  /* no distances specified, jump to pixel close to extent */
1580  if (d0) {
1581  if (x < 0)
1582  x = -1;
1583  else if (x > band->width)
1584  x = band->width;
1585 
1586  if (y < 0)
1587  y = -1;
1588  else if (y > band->height)
1589  y = band->height;
1590 
1591  RASTER_DEBUGF(4, "Moved selected pixel: %d x %d", x, y);
1592  }
1593  /*
1594  distances specified
1595  if distances won't capture extent of band, return 0
1596  */
1597  else if (
1598  ((x < 0 && (uint32_t) abs(x) > distance[0]) || (x - band->width >= (int)distance[0])) ||
1599  ((y < 0 && (uint32_t) abs(y) > distance[1]) || (y - band->height >= (int)distance[1]))
1600  ) {
1601  RASTER_DEBUG(4, "No nearest pixels possible for provided pixel and distances");
1602  return 0;
1603  }
1604  }
1605 
1606  /* no NODATA, exclude is FALSE */
1607  if (!band->hasnodata)
1608  exclude_nodata_value = FALSE;
1609  /* band is NODATA and excluding NODATA */
1610  else if (exclude_nodata_value && band->isnodata) {
1611  RASTER_DEBUG(4, "No nearest pixels possible as band is NODATA and excluding NODATA values");
1612  return 0;
1613  }
1614 
1615  /* determine the maximum distance to prevent an infinite loop */
1616  if (d0) {
1617  int a, b;
1618 
1619  /* X axis */
1620  a = abs(x);
1621  b = abs(x - band->width);
1622 
1623  if (a > b)
1624  distance[0] = a;
1625  else
1626  distance[0] = b;
1627 
1628  /* Y axis */
1629  a = abs(y);
1630  b = abs(y - band->height);
1631  if (a > b)
1632  distance[1] = a;
1633  else
1634  distance[1] = b;
1635 
1636  RASTER_DEBUGF(4, "Maximum distances: %d x %d", distance[0], distance[1]);
1637  }
1638 
1639  /* minimum possible value for pixel type */
1640  minval = rt_pixtype_get_min_value(band->pixtype);
1641  RASTER_DEBUGF(4, "pixtype: %s", rt_pixtype_name(band->pixtype));
1642  RASTER_DEBUGF(4, "minval: %f", minval);
1643 
1644  /* set variables */
1645  count = 0;
1646  *npixels = NULL;
1647 
1648  /* maximum extent */
1649  max_extent[0] = x - (int)distance[0]; /* min X */
1650  max_extent[1] = y - (int)distance[1]; /* min Y */
1651  max_extent[2] = x + (int)distance[0]; /* max X */
1652  max_extent[3] = y + (int)distance[1]; /* max Y */
1653  RASTER_DEBUGF(4, "Maximum Extent: (%d, %d, %d, %d)",
1654  max_extent[0], max_extent[1], max_extent[2], max_extent[3]);
1655 
1656  _d[0] = 0;
1657  _d[1] = 0;
1658  do {
1659  _d[0]++;
1660  _d[1]++;
1661 
1662  extent[0] = x - (int)_d[0]; /* min x */
1663  extent[1] = y - (int)_d[1]; /* min y */
1664  extent[2] = x + (int)_d[0]; /* max x */
1665  extent[3] = y + (int)_d[1]; /* max y */
1666 
1667  RASTER_DEBUGF(4, "Processing distances: %d x %d", _d[0], _d[1]);
1668  RASTER_DEBUGF(4, "Extent: (%d, %d, %d, %d)",
1669  extent[0], extent[1], extent[2], extent[3]);
1670 
1671  for (i = 0; i < 2; i++) {
1672 
1673  /* by row */
1674  if (i < 1)
1675  _max = extent[2] - extent[0] + 1;
1676  /* by column */
1677  else
1678  _max = extent[3] - extent[1] + 1;
1679  _max = abs(_max);
1680 
1681  for (j = 0; j < 2; j++) {
1682  /* by row */
1683  if (i < 1) {
1684  _x = extent[0];
1685  _min = &_x;
1686 
1687  /* top row */
1688  if (j < 1)
1689  _y = extent[1];
1690  /* bottom row */
1691  else
1692  _y = extent[3];
1693  }
1694  /* by column */
1695  else {
1696  _y = extent[1] + 1;
1697  _min = &_y;
1698 
1699  /* left column */
1700  if (j < 1) {
1701  _x = extent[0];
1702  _max -= 2;
1703  }
1704  /* right column */
1705  else
1706  _x = extent[2];
1707  }
1708 
1709  RASTER_DEBUGF(4, "_min, _max: %d, %d", *_min, _max);
1710  for (k = 0; k < (uint32_t) _max; k++) {
1711  /* check that _x and _y are not outside max extent */
1712  if (
1713  _x < max_extent[0] || _x > max_extent[2] ||
1714  _y < max_extent[1] || _y > max_extent[3]
1715  ) {
1716  (*_min)++;
1717  continue;
1718  }
1719 
1720  /* outside band extent, set to NODATA */
1721  if (
1722  (_x < 0 || _x >= band->width) ||
1723  (_y < 0 || _y >= band->height)
1724  ) {
1725  /* no NODATA, set to minimum possible value */
1726  if (!band->hasnodata)
1727  pixval = minval;
1728  /* has NODATA, use NODATA */
1729  else
1730  pixval = band->nodataval;
1731  RASTER_DEBUGF(4, "NODATA pixel outside band extent: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1732  inextent = 0;
1733  isnodata = 1;
1734  }
1735  else {
1736  if (rt_band_get_pixel(
1737  band,
1738  _x, _y,
1739  &pixval,
1740  &isnodata
1741  ) != ES_NONE) {
1742  rterror("rt_band_get_nearest_pixel: Could not get pixel value");
1743  if (count) rtdealloc(*npixels);
1744  return -1;
1745  }
1746  RASTER_DEBUGF(4, "Pixel: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1747  inextent = 1;
1748  }
1749 
1750  /* use pixval? */
1751  if (!exclude_nodata_value || (exclude_nodata_value && !isnodata)) {
1752  /* add pixel to result set */
1753  RASTER_DEBUGF(4, "Adding pixel to set of nearest pixels: (x, y, val) = (%d, %d, %f)", _x, _y, pixval);
1754  count++;
1755 
1756  if (*npixels == NULL)
1757  *npixels = (rt_pixel) rtalloc(sizeof(struct rt_pixel_t) * count);
1758  else
1759  *npixels = (rt_pixel) rtrealloc(*npixels, sizeof(struct rt_pixel_t) * count);
1760  if (*npixels == NULL) {
1761  rterror("rt_band_get_nearest_pixel: Could not allocate memory for nearest pixel(s)");
1762  return -1;
1763  }
1764 
1765  npixel = &((*npixels)[count - 1]);
1766  npixel->x = _x;
1767  npixel->y = _y;
1768  npixel->value = pixval;
1769 
1770  /* special case for when outside band extent */
1771  if (!inextent && !band->hasnodata)
1772  npixel->nodata = 1;
1773  else
1774  npixel->nodata = 0;
1775  }
1776 
1777  (*_min)++;
1778  }
1779  }
1780  }
1781 
1782  /* distance threshholds met */
1783  if (_d[0] >= distance[0] && _d[1] >= distance[1])
1784  break;
1785  else if (d0 && count)
1786  break;
1787  }
1788  while (1);
1789 
1790  RASTER_DEBUGF(3, "Nearest pixels in return: %d", count);
1791 
1792  return count;
1793 }
#define FALSE
Definition: dbfopen.c:72
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition: rt_context.c:219
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition: rt_context.c:191
#define RASTER_DEBUG(level, msg)
Definition: librtcore.h:302
#define RASTER_DEBUGF(level, msg,...)
Definition: librtcore.h:306
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_pixel.c:150
struct rt_pixel_t * rt_pixel
Definition: librtcore.h:149
@ ES_NONE
Definition: librtcore.h:182
void * rtrealloc(void *mem, size_t size)
Definition: rt_context.c:199
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
void rtdealloc(void *mem)
Definition: rt_context.c:206
static double distance(double x1, double y1, double x2, double y2)
Definition: lwtree.c:1032
int count
Definition: genraster.py:57
band
Definition: ovdump.py:58
pixval
Definition: pixval.py:94
Definition: pixval.py:1
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1376
double value
Definition: librtcore.h:2491
uint8_t nodata
Definition: librtcore.h:2490

References ovdump::band, genraster::count, distance(), ES_NONE, FALSE, rt_pixel_t::nodata, 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_pixel_t::x, pixval::x, rt_pixel_t::y, and pixval::y.

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

Here is the call graph for this function:
Here is the caller graph for this function: