123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- /*!
- \file lib/raster/sample.c
- \brief Raster library - Sampling methods (extract a cell value from
- raster map)
- 1/2006: moved to libgis from v.sample/v.drape for clone removal
- (C) 2001-2009 by the GRASS Development Team
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
- \author James Darrell McCauley <darrell mccauley-usa.com>, http://mccauley-usa.com/
- */
- #include <string.h>
- #include <unistd.h>
- #include <math.h>
- #include <grass/gis.h>
- #include <grass/raster.h>
- #include <grass/glocale.h>
- /* prototypes */
- static double scancatlabel(const char *);
- /*!
- * \brief Extract a cell value from raster map.
- *
- * Extract a cell value from raster map at given northing and easting
- * with a sampled 3x3 window using a specified interpolation method.
- *
- * - NEAREST neighbor interpolation
- * - BILINEAR bilinear interpolation
- * - CUBIC cubic interpolation
- *
- * \param fd file descriptor
- * \param window region settings
- * \param cats categories
- * \param north northing position
- * \param east easting position
- * \param usedesc flag to scan category label
- * \param itype interpolation method
- *
- * \return cell value at given position
- */
- DCELL Rast_get_sample(int fd,
- const struct Cell_head *window,
- struct Categories *cats,
- double north, double east,
- int usedesc, INTERP_TYPE itype)
- {
- double retval;
- switch (itype) {
- case INTERP_NEAREST:
- retval =
- Rast_get_sample_nearest(fd, window, cats, north, east, usedesc);
- break;
- case INTERP_BILINEAR:
- retval =
- Rast_get_sample_bilinear(fd, window, cats, north, east, usedesc);
- break;
- case INTERP_BICUBIC:
- retval =
- Rast_get_sample_cubic(fd, window, cats, north, east, usedesc);
- break;
- default:
- G_fatal_error("Rast_get_sample: %s", _("Unknown interpolation type"));
- }
- return retval;
- }
- /*!
- * \brief Extract a cell value from raster map (neighbor interpolation)
- *
- * Extract a cell value from raster map at given northing and easting
- * with a sampled 3x3 window using a neighbor interpolation.
- *
- * \param fd file descriptor
- * \param window region settings
- * \param cats categories
- * \param north northing position
- * \param east easting position
- * \param usedesc flag to scan category label
- *
- * \return cell value at given position
- */
- DCELL Rast_get_sample_nearest(int fd,
- const struct Cell_head * window,
- struct Categories * cats,
- double north, double east, int usedesc)
- {
- int row, col;
- DCELL result;
- DCELL *maprow = Rast_allocate_d_buf();
- /* convert northing and easting to row and col, resp */
- row = (int)floor(Rast_northing_to_row(north, window));
- col = (int)floor(Rast_easting_to_col(east, window));
- if (row < 0 || row >= Rast_window_rows() ||
- col < 0 || col >= Rast_window_cols()) {
- Rast_set_d_null_value(&result, 1);
- goto done;
- }
- Rast_get_d_row(fd, maprow, row);
- if (Rast_is_d_null_value(&maprow[col])) {
- Rast_set_d_null_value(&result, 1);
- goto done;
- }
- if (usedesc) {
- char *buf = Rast_get_c_cat((CELL *) & (maprow[col]), cats);
- G_squeeze(buf);
- result = scancatlabel(buf);
- }
- else
- result = maprow[col];
- done:
- G_free(maprow);
- return result;
- }
- /*!
- * \brief Extract a cell value from raster map (bilinear interpolation).
- *
- * Extract a cell value from raster map at given northing and easting
- * with a sampled 3x3 window using a bilinear interpolation.
- *
- * \param fd file descriptor
- * \param window region settings
- * \param cats categories
- * \param north northing position
- * \param east easting position
- * \param usedesc flag to scan category label
- *
- * \return cell value at given position
- */
- DCELL Rast_get_sample_bilinear(int fd,
- const struct Cell_head * window,
- struct Categories * cats,
- double north, double east, int usedesc)
- {
- int row, col;
- double grid[2][2];
- DCELL *arow = Rast_allocate_d_buf();
- DCELL *brow = Rast_allocate_d_buf();
- double frow, fcol, trow, tcol;
- DCELL result;
- frow = Rast_northing_to_row(north, window);
- fcol = Rast_easting_to_col(east, window);
- /* convert northing and easting to row and col, resp */
- row = (int)floor(frow - 0.5);
- col = (int)floor(fcol - 0.5);
- trow = frow - row - 0.5;
- tcol = fcol - col - 0.5;
- if (row < 0 || row + 1 >= Rast_window_rows() ||
- col < 0 || col + 1 >= Rast_window_cols()) {
- Rast_set_d_null_value(&result, 1);
- goto done;
- }
- Rast_get_d_row(fd, arow, row);
- Rast_get_d_row(fd, brow, row + 1);
- if (Rast_is_d_null_value(&arow[col]) ||
- Rast_is_d_null_value(&arow[col + 1]) ||
- Rast_is_d_null_value(&brow[col]) ||
- Rast_is_d_null_value(&brow[col + 1])) {
- Rast_set_d_null_value(&result, 1);
- goto done;
- }
- /*-
- * now were ready to do bilinear interpolation over
- * arow[col], arow[col+1],
- * brow[col], brow[col+1]
- */
- if (usedesc) {
- char *buf;
- G_squeeze(buf = Rast_get_c_cat((int *)&(arow[col]), cats));
- grid[0][0] = scancatlabel(buf);
- G_squeeze(buf = Rast_get_c_cat((CELL *) & (arow[col + 1]), cats));
- grid[0][1] = scancatlabel(buf);
- G_squeeze(buf = Rast_get_c_cat((CELL *) & (brow[col]), cats));
- grid[1][0] = scancatlabel(buf);
- G_squeeze(buf = Rast_get_c_cat((CELL *) & (brow[col + 1]), cats));
- grid[1][1] = scancatlabel(buf);
- }
- else {
- grid[0][0] = arow[col];
- grid[0][1] = arow[col + 1];
- grid[1][0] = brow[col];
- grid[1][1] = brow[col + 1];
- }
- result = Rast_interp_bilinear(tcol, trow,
- grid[0][0], grid[0][1], grid[1][0],
- grid[1][1]);
- done:
- G_free(arow);
- G_free(brow);
- return result;
- }
- /*!
- * \brief Extract a cell value from raster map (cubic interpolation).
- *
- * Extract a cell value from raster map at given northing and easting
- * with a sampled 3x3 window using a cubic interpolation.
- *
- * \param fd file descriptor
- * \param window region settings
- * \param cats categories
- * \param north northing position
- * \param east easting position
- * \param usedesc flag to scan category label
- *
- * \return cell value at given position
- */
- DCELL Rast_get_sample_cubic(int fd,
- const struct Cell_head * window,
- struct Categories * cats,
- double north, double east, int usedesc)
- {
- int i, j, row, col;
- double grid[4][4];
- DCELL *rows[4];
- double frow, fcol, trow, tcol;
- DCELL result;
- for (i = 0; i < 4; i++)
- rows[i] = Rast_allocate_d_buf();
- frow = Rast_northing_to_row(north, window);
- fcol = Rast_easting_to_col(east, window);
- /* convert northing and easting to row and col, resp */
- row = (int)floor(frow - 1.5);
- col = (int)floor(fcol - 1.5);
- trow = frow - row - 1.5;
- tcol = fcol - col - 1.5;
- if (row < 0 || row + 3 >= Rast_window_rows() ||
- col < 0 || col + 3 >= Rast_window_cols()) {
- Rast_set_d_null_value(&result, 1);
- goto done;
- }
- for (i = 0; i < 4; i++)
- Rast_get_d_row(fd, rows[i], row + i);
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- if (Rast_is_d_null_value(&rows[i][col + j])) {
- Rast_set_d_null_value(&result, 1);
- goto done;
- }
- /*
- * now were ready to do cubic interpolation over
- * arow[col], arow[col+1], arow[col+2], arow[col+3],
- * brow[col], brow[col+1], brow[col+2], brow[col+3],
- * crow[col], crow[col+1], crow[col+2], crow[col+3],
- * drow[col], drow[col+1], drow[col+2], drow[col+3],
- */
- if (usedesc) {
- char *buf;
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- G_squeeze(buf =
- Rast_get_c_cat((CELL *) & (rows[i][col + j]),
- cats));
- grid[i][j] = scancatlabel(buf);
- }
- }
- }
- else {
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- grid[i][j] = rows[i][col + j];
- }
- result = Rast_interp_bicubic(tcol, trow,
- grid[0][0], grid[0][1], grid[0][2],
- grid[0][3], grid[1][0], grid[1][1],
- grid[1][2], grid[1][3], grid[2][0],
- grid[2][1], grid[2][2], grid[2][3],
- grid[3][0], grid[3][1], grid[3][2],
- grid[3][3]);
- done:
- for (i = 0; i < 4; i++)
- G_free(rows[i]);
- return result;
- }
- static double scancatlabel(const char *str)
- {
- double val;
- if (strcmp(str, "no data") != 0)
- sscanf(str, "%lf", &val);
- else {
- G_warning(_("\"no data\" label found; setting to zero"));
- val = 0.0;
- }
- return val;
- }
|