/************************************************************* * G__create_window_mapping(fd) * int fd file descriptor for map to be mapped * * function: * create 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. * parms: * fd: open file descriptor for cell file * * called by: * G_open_cell_old() * G_set_window() *************************************************************** * G_window_rows(), G_window_cols() * * function * return the number of rows, cols in the current window * * parms: (none) * * called by * any user program *************************************************************/ #include #include #include "G.h" int G__create_window_mapping (int fd) { struct fileinfo *fcb = &G__.fileinfo[fd]; COLUMN_MAPPING *col; int i; int x; double C1, C2; double west; G__init_window () ; #define alloc_index(n) (COLUMN_MAPPING *) G_malloc((n)*sizeof(COLUMN_MAPPING)) if (fcb->open_mode >= 0 && fcb->open_mode != OPEN_OLD) /* open for write? */ return 0; if (fcb->open_mode == OPEN_OLD) /* already open ? */ G_free (fcb->col_map); col = fcb->col_map = alloc_index (G__.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 = G__.window.west; if (G__.window.proj == PROJECTION_LL) { while (west > fcb->cellhd.west + 360.0) west -=360.0; while (west < fcb->cellhd.west) west += 360.0; } C1 = G__.window.ew_res / fcb->cellhd.ew_res ; C2 = (west - fcb->cellhd.west + G__.window.ew_res/2.0) / fcb->cellhd.ew_res; for (i = 0; i < G__.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 (G__.window.proj == PROJECTION_LL) { col = fcb->col_map; C2 = (west - 360.0 - fcb->cellhd.west + G__.window.ew_res/2.0) / fcb->cellhd.ew_res; for (i = 0; i < G__.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; } } #ifdef DEBUG fprintf (stderr, "create window mapping (%d cols)", G__.window.cols); for (i = 0; i < G__.window.cols; i++) fprintf (stderr, "%s%ld", i%15?" ":"\n", (long)fcb->col_map[i]); fprintf (stderr, "\n"); #endif /* * compute C1,C2 for row window mapping */ fcb->C1 = G__.window.ns_res / fcb->cellhd.ns_res ; fcb->C2 = (fcb->cellhd.north - G__.window.north + G__.window.ns_res/2.0) / fcb->cellhd.ns_res; return 0; } /*! * \brief northing to row * * Converts a northing relative to a * region to a row. * Note. the result is a double. Casting it to an integer will give the * row number. * * \param north * \param region * \return double */ double G_northing_to_row (double north, struct Cell_head *window) { return (window->north - north) / window->ns_res; } /*! * \brief adjust east longitude * * This routine returns an equivalent east that is * larger, but no more than 360 larger than the west coordinate. * This routine should be used only with latitude-longitude coordinates. * * \param east * \param west * \return double */ double G_adjust_east_longitude ( double east,double west) { while (east > west + 360.0) east -=360.0; while (east <= west) east += 360.0; return east; } /*! * \brief returns east larger than west * * If the region projection is * PROJECTION_LL, then this routine returns an equivalent east that is * larger, but no more than 360 degrees larger, than the coordinate for the * western edge of the region. Otherwise no adjustment is made and the original * east is returned. * * \param east * \param region * \return double */ double G_adjust_easting ( double east, struct Cell_head *window) { if (window->proj == PROJECTION_LL) { east = G_adjust_east_longitude(east, window->west); if (east > window->east && east == window->west + 360) east = window->west; } return east; } double G_easting_to_col ( double east, struct Cell_head *window) { east = G_adjust_easting (east, window); return (east - window->west) / window->ew_res; } /* note: row is a double. * row+0.5 will give center * row+0.0 will give northern edge of row * row+1.0 will give southern edge of row */ /*! * \brief row to northing * * Converts a row relative to a region to a * northing; * Note. row is a double: row+0.5 will return the northing for the * center of the row; row+0.0 will return the northing for the northern edge of * the row; and row+1.0 will return the northing for the southern edge of the * row. double G_easting_to_col (east, region) easting to * column double east; struct Cell_head *region; * Converts an easting relative to a region to a column. * Note. The result is a double. Casting it to an integer will give the * column number. * * \param row * \param region * \return double */ double G_row_to_northing ( double row, struct Cell_head *window) { return window->north - row * window->ns_res; } /*! * \brief column to easting * * Converts a column relative to a * region to an easting; * Note. col is a double: col+0.5 will return the easting for the center * of the column; col+0.0 will return the easting for the western edge of the * column; and col+1.0 will return the easting for the eastern edge of the * column. * * \param col * \param region * \return double */ double G_col_to_easting (double col, struct Cell_head *window) { return window->west + col * window->ew_res; } /*! * \brief number of rows in active region * * * \param void * \return int */ int G_window_rows () { G__init_window () ; return G__.window.rows; } /*! * \brief number of columns in active region * * These * routines return the number of rows and columns (respectively) in the active * module region. Before raster files can be read or written, it is necessary to * known how many rows and columns are in the active region. For example: \code int nrows, cols; int row, col; nrows = G_window_rows( ); ncols = G_window_cols( ); for (row = 0; row < nrows; row++) { read row ... for (col = 0; col < ncols; col++) { process col ... } } \endcode * * \param void * \return int */ int G_window_cols () { G__init_window () ; return G__.window.cols; } int G__init_window () { if (!G__.window_set) { G__.window_set = 1; G_get_window (&G__.window); } return 0; } /* this routine works fine if the mask is not set * may give incorrect results with a mask, since the * mask row may have a different repeat value * can be fixed by doing it for the mask as well and using * the smaller value */ int G_row_repeat_nomask (int fd, int row) { struct fileinfo *fcb = &G__.fileinfo[fd]; double f; int r1, r2; int count; count = 1; /* r1 is the row in the cell file itself. * r2 is the next row(s) in the cell file * see get_row.c for details on this calculation */ f = row * fcb->C1 + fcb->C2; r1 = f; if (f < r1) r1--; while (++row < G__.window.rows) { f = row * fcb->C1 + fcb->C2; r2 = f; if (f < r2) r2--; if (r1 != r2) break; count++; } return count; }