/*! * \file lib/raster/window_map.c * * \brief Raster Library - Window mapping functions. * * (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 Original author CERL */ #include #include #include #include "R.h" #define alloc_index(n) (COLUMN_MAPPING *) G_malloc((n)*sizeof(COLUMN_MAPPING)) /*! * \brief Create window mapping. * * Creates mapping from cell header into window. The boundaries and * resolution of the two spaces do not have to be the same or aligned in * any way. * * \param fd file descriptor */ void Rast__create_window_mapping(int fd) { struct fileinfo *fcb = &R__.fileinfo[fd]; COLUMN_MAPPING *col; int i; int x; double C1, C2; double west, east; if (fcb->open_mode >= 0 && fcb->open_mode != OPEN_OLD) /* open for write? */ return; if (fcb->open_mode == OPEN_OLD) /* already open ? */ G_free(fcb->col_map); col = fcb->col_map = alloc_index(R__.rd_window.cols); /* * for each column in the window, go to center of the cell, * compute nearest column in the data file * if column is not in data file, set column to 0 * * for lat/lon move window so that west is bigger than * cellhd west. */ west = R__.rd_window.west; east = R__.rd_window.east; if (R__.rd_window.proj == PROJECTION_LL) { while (west > fcb->cellhd.west + 360.0) { west -= 360.0; east -= 360.0; } while (west < fcb->cellhd.west) { west += 360.0; east += 360.0; } } C1 = R__.rd_window.ew_res / fcb->cellhd.ew_res; C2 = (west - fcb->cellhd.west + R__.rd_window.ew_res / 2.0) / fcb->cellhd.ew_res; for (i = 0; i < R__.rd_window.cols; i++) { x = C2; if (C2 < x) /* adjust for rounding of negatives */ x--; if (x < 0 || x >= fcb->cellhd.cols) /* not in data file */ x = -1; *col++ = x + 1; C2 += C1; } /* do wrap around for lat/lon */ if (R__.rd_window.proj == PROJECTION_LL) { while (east - 360.0 > fcb->cellhd.west) { east -= 360.0; west -= 360.0; col = fcb->col_map; C2 = (west - fcb->cellhd.west + R__.rd_window.ew_res / 2.0) / fcb->cellhd.ew_res; for (i = 0; i < R__.rd_window.cols; i++) { x = C2; if (C2 < x) /* adjust for rounding of negatives */ x--; if (x < 0 || x >= fcb->cellhd.cols) /* not in data file */ x = -1; if (*col == 0) /* only change those not already set */ *col = x + 1; col++; C2 += C1; } } } G_debug(3, "create window mapping (%d columns)", R__.rd_window.cols); /* for (i = 0; i < R__.rd_window.cols; i++) fprintf(stderr, "%s%ld", i % 15 ? " " : "\n", (long)fcb->col_map[i]); fprintf(stderr, "\n"); */ /* compute C1,C2 for row window mapping */ fcb->C1 = R__.rd_window.ns_res / fcb->cellhd.ns_res; fcb->C2 = (fcb->cellhd.north - R__.rd_window.north + R__.rd_window.ns_res / 2.0) / fcb->cellhd.ns_res; } /*! * \brief Loops rows until mismatch?. * * This routine works fine if the mask is not set. It may give * incorrect results with a mask, since the mask row may have a * different repeat value. The issue can be fixed by doing it for the * mask as well and using the smaller value. * * \param fd file descriptor * \param row starting row * * \return number of rows completed */ int Rast_row_repeat_nomask(int fd, int row) { struct fileinfo *fcb = &R__.fileinfo[fd]; double f; int r1, r2; int count; count = 1; /* r1 is the row in the raster map itself. * r2 is the next row(s) in the raster map * see get_row.c for details on this calculation */ f = row * fcb->C1 + fcb->C2; r1 = f; if (f < r1) r1--; while (++row < R__.rd_window.rows) { f = row * fcb->C1 + fcb->C2; r2 = f; if (f < r2) r2--; if (r1 != r2) break; count++; } return count; }