Loading...
Searching...
No Matches
adj_cellhd.c
Go to the documentation of this file.
/*!
* \file lib/gis/adj_cellhd.c
*
* \brief GIS Library - CELL header adjustment.
*
* (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 <math.h>
#include <string.h>
#include <grass/gis.h>
#include <grass/glocale.h>
#define LL_TOLERANCE 10
/* TODO: find good thresholds */
/* deviation measured in cells */
static double llepsilon = 0.01;
static double fpepsilon = 1.0e-9;
static int ll_wrap(struct Cell_head *cellhd);
static int ll_check_ns(struct Cell_head *cellhd);
static int ll_check_ew(struct Cell_head *cellhd);
/*!
* \brief Adjust cell header.
*
* This function fills in missing parts of the input cell header (or
* region). It also makes projection-specific adjustments. The
* <i>cellhd</i> structure must have its <i>north, south, east,
* west</i>, and <i>proj</i> fields set.
*
* If <i>row_flag</i> is true, then the north-south resolution is
* computed from the number of <i>rows</i> in the <i>cellhd</i>
* structure. Otherwise the number of <i>rows</i> is computed from the
* north-south resolution in the structure, similarly for
* <i>col_flag</i> and the number of columns and the east-west
* resolution.
*
* <b>Note:</b> 3D values are not adjusted.
*
* \param[in,out] cellhd pointer to Cell_head structure
* \param row_flag compute n-s resolution
* \param col_flag compute e-w resolution
*/
void G_adjust_Cell_head(struct Cell_head *cellhd, int row_flag, int col_flag)
{
double old_res;
if (!row_flag) {
if (cellhd->ns_res <= 0)
G_fatal_error(_("Illegal n-s resolution value: %g"),
cellhd->ns_res);
}
else {
if (cellhd->rows <= 0)
G_fatal_error(_("Illegal number of rows: %d"
" (resolution is %g)"),
cellhd->rows, cellhd->ns_res);
}
if (!col_flag) {
if (cellhd->ew_res <= 0)
G_fatal_error(_("Illegal e-w resolution value: %g"),
cellhd->ew_res);
}
else {
if (cellhd->cols <= 0)
G_fatal_error(_("Illegal number of columns: %d"
" (resolution is %g)"),
cellhd->cols, cellhd->ew_res);
}
/* check the edge values */
if (cellhd->north <= cellhd->south) {
if (cellhd->proj == PROJECTION_LL)
G_fatal_error(_("North must be north of South,"
" but %g (north) <= %g (south"),
cellhd->north, cellhd->south);
else
G_fatal_error(_("North must be larger than South,"
" but %g (north) <= %g (south"),
cellhd->north, cellhd->south);
}
ll_wrap(cellhd);
if (cellhd->east <= cellhd->west)
G_fatal_error(_("East must be larger than West,"
" but %g (east) <= %g (west)"),
cellhd->east, cellhd->west);
/* compute rows and columns, if not set */
if (!row_flag) {
cellhd->rows = (cellhd->north - cellhd->south + cellhd->ns_res / 2.0) /
cellhd->ns_res;
if (cellhd->rows == 0)
cellhd->rows = 1;
}
if (!col_flag) {
cellhd->cols = (cellhd->east - cellhd->west + cellhd->ew_res / 2.0) /
cellhd->ew_res;
if (cellhd->cols == 0)
cellhd->cols = 1;
}
if (cellhd->cols < 0) {
G_fatal_error(_("Invalid coordinates: negative number of columns"));
}
if (cellhd->rows < 0) {
G_fatal_error(_("Invalid coordinates: negative number of rows"));
}
/* (re)compute the resolutions */
old_res = cellhd->ns_res;
cellhd->ns_res = (cellhd->north - cellhd->south) / cellhd->rows;
if (old_res > 0 && fabs(old_res - cellhd->ns_res) / old_res > 0.01)
G_verbose_message(_("NS resolution has been changed"));
old_res = cellhd->ew_res;
cellhd->ew_res = (cellhd->east - cellhd->west) / cellhd->cols;
if (old_res > 0 && fabs(old_res - cellhd->ew_res) / old_res > 0.01)
G_verbose_message(_("EW resolution has been changed"));
if (fabs(cellhd->ns_res - cellhd->ew_res) / cellhd->ns_res > 0.01)
G_verbose_message(_("NS and EW resolutions are different"));
ll_check_ns(cellhd);
ll_check_ew(cellhd);
}
/*!
* \brief Adjust cell header for 3D values.
*
* This function fills in missing parts of the input cell header (or
* region). It also makes projection-specific adjustments. The
* <i>cellhd</i> structure must have its <i>north, south, east,
* west</i>, and <i>proj</i> fields set.
*
* If <i>row_flag</i> is true, then the north-south resolution is computed
* from the number of <i>rows</i> in the <i>cellhd</i> structure.
* Otherwise the number of <i>rows</i> is computed from the north-south
* resolution in the structure, similarly for <i>col_flag</i> and the
* number of columns and the east-west resolution.
*
* If <i>depth_flag</i> is true, top-bottom resolution is calculated
* from depths.
* If <i>depth_flag</i> are false, number of depths is calculated from
* top-bottom resolution.
*
* \warning This function can cause segmentation fault without any warning
* when it is called with Cell_head top and bottom set to zero.
*
* \param[in,out] cellhd pointer to Cell_head structure
* \param row_flag compute n-s resolution
* \param col_flag compute e-w resolution
* \param depth_flag compute t-b resolution
*/
void G_adjust_Cell_head3(struct Cell_head *cellhd, int row_flag, int col_flag,
int depth_flag)
{
double old_res;
if (!row_flag) {
if (cellhd->ns_res <= 0)
G_fatal_error(_("Illegal n-s resolution value: %g"),
cellhd->ns_res);
if (cellhd->ns_res3 <= 0)
G_fatal_error(_("Illegal n-s resolution value for 3D: %g"),
cellhd->ns_res3);
}
else {
if (cellhd->rows <= 0)
G_fatal_error(_("Illegal number of rows: %d"
" (resolution is %g)"),
cellhd->rows, cellhd->ns_res);
if (cellhd->rows3 <= 0)
G_fatal_error(_("Illegal number of rows for 3D: %d"
" (resolution is %g)"),
cellhd->rows3, cellhd->ns_res3);
}
if (!col_flag) {
if (cellhd->ew_res <= 0)
G_fatal_error(_("Illegal e-w resolution value: %g"),
cellhd->ew_res);
if (cellhd->ew_res3 <= 0)
G_fatal_error(_("Illegal e-w resolution value for 3D: %g"),
cellhd->ew_res3);
}
else {
if (cellhd->cols <= 0)
G_fatal_error(_("Illegal number of columns: %d"
" (resolution is %g)"),
cellhd->cols, cellhd->ew_res);
if (cellhd->cols3 <= 0)
G_fatal_error(_("Illegal number of columns for 3D: %d"
" (resolution is %g)"),
cellhd->cols3, cellhd->ew_res3);
}
if (!depth_flag) {
if (cellhd->tb_res <= 0)
G_fatal_error(_("Illegal t-b resolution value: %g"),
cellhd->tb_res);
}
else {
if (cellhd->depths <= 0)
G_fatal_error(_("Illegal depths value: %d"), cellhd->depths);
}
/* check the edge values */
if (cellhd->north <= cellhd->south) {
if (cellhd->proj == PROJECTION_LL)
G_fatal_error(_("North must be north of South,"
" but %g (north) <= %g (south"),
cellhd->north, cellhd->south);
else
G_fatal_error(_("North must be larger than South,"
" but %g (north) <= %g (south"),
cellhd->north, cellhd->south);
}
ll_wrap(cellhd);
if (cellhd->east <= cellhd->west)
G_fatal_error(_("East must be larger than West,"
" but %g (east) <= %g (west)"),
cellhd->east, cellhd->west);
if (cellhd->top <= cellhd->bottom)
G_fatal_error(_("Top must be larger than Bottom,"
" but %g (top) <= %g (bottom)"),
cellhd->top, cellhd->bottom);
/* compute rows and columns, if not set */
if (!row_flag) {
cellhd->rows = (cellhd->north - cellhd->south + cellhd->ns_res / 2.0) /
cellhd->ns_res;
if (cellhd->rows == 0)
cellhd->rows = 1;
cellhd->rows3 =
(cellhd->north - cellhd->south + cellhd->ns_res3 / 2.0) /
cellhd->ns_res3;
if (cellhd->rows3 == 0)
cellhd->rows3 = 1;
}
if (!col_flag) {
cellhd->cols = (cellhd->east - cellhd->west + cellhd->ew_res / 2.0) /
cellhd->ew_res;
if (cellhd->cols == 0)
cellhd->cols = 1;
cellhd->cols3 = (cellhd->east - cellhd->west + cellhd->ew_res3 / 2.0) /
cellhd->ew_res3;
if (cellhd->cols3 == 0)
cellhd->cols3 = 1;
}
if (!depth_flag) {
cellhd->depths = (cellhd->top - cellhd->bottom + cellhd->tb_res / 2.0) /
cellhd->tb_res;
if (cellhd->depths == 0)
cellhd->depths = 1;
}
if (cellhd->cols < 0 || cellhd->cols3 < 0) {
G_fatal_error(_("Invalid coordinates: negative number of columns"));
}
if (cellhd->rows < 0 || cellhd->rows3 < 0) {
G_fatal_error(_("Invalid coordinates: negative number of rows"));
}
if (cellhd->depths < 0) {
G_fatal_error(_("Invalid coordinates: negative number of depths"));
}
/* (re)compute the resolutions */
old_res = cellhd->ns_res;
cellhd->ns_res = (cellhd->north - cellhd->south) / cellhd->rows;
if (old_res > 0 && fabs(old_res - cellhd->ns_res) / old_res > 0.01)
G_verbose_message(_("NS resolution has been changed"));
old_res = cellhd->ew_res;
cellhd->ew_res = (cellhd->east - cellhd->west) / cellhd->cols;
if (old_res > 0 && fabs(old_res - cellhd->ew_res) / old_res > 0.01)
G_verbose_message(_("EW resolution has been changed"));
if (fabs(cellhd->ns_res - cellhd->ew_res) / cellhd->ns_res > 0.01)
G_verbose_message(_("NS and EW resolutions are different"));
ll_check_ns(cellhd);
ll_check_ew(cellhd);
cellhd->ns_res3 = (cellhd->north - cellhd->south) / cellhd->rows3;
cellhd->ew_res3 = (cellhd->east - cellhd->west) / cellhd->cols3;
cellhd->tb_res = (cellhd->top - cellhd->bottom) / cellhd->depths;
}
static int ll_wrap(struct Cell_head *cellhd)
{
double shift;
/* for lat/lon, force east larger than west, try to wrap to -180, 180 */
if (cellhd->proj != PROJECTION_LL)
return 0;
if (cellhd->east <= cellhd->west) {
G_warning(_("East (%.15g) is not larger than West (%.15g)"),
cellhd->east, cellhd->west);
while (cellhd->east <= cellhd->west)
cellhd->east += 360.0;
}
/* with east larger than west,
* any 360 degree W-E extent can be represented within -360, 360
* but not within -180, 180 */
/* try to shift to within -180, 180 */
shift = 0;
while (cellhd->west + shift >= 180) {
shift -= 360.0;
}
while (cellhd->east + shift <= -180) {
shift += 360.0;
}
/* try to shift to within -360, 360 */
while (cellhd->east + shift > 360) {
shift -= 360.0;
}
while (cellhd->west + shift <= -360) {
shift += 360.0;
}
if (shift) {
cellhd->west += shift;
cellhd->east += shift;
}
/* very liberal thresholds */
if (cellhd->north > 90.0 + LL_TOLERANCE)
G_fatal_error(_("Illegal latitude for North: %g"), cellhd->north);
if (cellhd->south < -90.0 - LL_TOLERANCE)
G_fatal_error(_("Illegal latitude for South: %g"), cellhd->south);
#if 0
/* disabled: allow W-E extents larger than 360 degree e.g. for display */
if (cellhd->west < -360.0 - LL_TOLERANCE) {
G_debug(1, "East: %g", cellhd->east);
G_fatal_error(_("Illegal longitude for West: %g"), cellhd->west);
}
if (cellhd->east > 360.0 + LL_TOLERANCE) {
G_debug(1, "West: %g", cellhd->west);
G_fatal_error(_("Illegal longitude for East: %g"), cellhd->east);
}
#endif
return 1;
}
static int ll_check_ns(struct Cell_head *cellhd)
{
int lladjust;
double diff;
int ncells;
/* lat/lon checks */
if (cellhd->proj != PROJECTION_LL)
return 0;
lladjust = 0;
G_debug(3, "ll_check_ns: epsilon: %g", llepsilon);
/* North, South: allow a half cell spill-over */
diff = (cellhd->north - cellhd->south) / cellhd->ns_res;
ncells = (int)(diff + 0.5);
diff -= ncells;
if ((diff < 0 && diff < -fpepsilon) || (diff > 0 && diff > fpepsilon)) {
G_verbose_message(
_("NS extent does not match NS resolution: %g cells difference"),
diff);
}
/* north */
diff = (cellhd->north - 90) / cellhd->ns_res;
if (diff < 0)
diff = -diff;
if (cellhd->north < 90.0 && diff < 1.0) {
G_verbose_message(_("%g cells missing to reach 90 degree north"), diff);
if (diff < llepsilon && diff > fpepsilon) {
G_verbose_message(
_("Subtle input data rounding error of north boundary (%g)"),
cellhd->north - 90.0);
/* check only, do not modify
cellhd->north = 90.0;
lladjust = 1;
*/
}
}
if (cellhd->north > 90.0) {
if (diff <= 0.5 + llepsilon) {
G_important_message(_("90 degree north is exceeded by %g cells"),
diff);
if (diff < llepsilon && diff > fpepsilon) {
G_verbose_message(_("Subtle input data rounding error of north "
"boundary (%g)"),
cellhd->north - 90.0);
G_debug(1, "North of north in seconds: %g",
(cellhd->north - 90.0) * 3600);
/* check only, do not modify
cellhd->north = 90.0;
lladjust = 1;
*/
}
diff = diff - 0.5;
if (diff < 0)
diff = -diff;
if (diff < llepsilon && diff > fpepsilon) {
G_verbose_message(_("Subtle input data rounding error of north "
"boundary (%g)"),
cellhd->north - 90.0 - cellhd->ns_res / 2.0);
G_debug(1, "North of north + 0.5 cells in seconds: %g",
(cellhd->north - 90.0 - cellhd->ns_res / 2.0) * 3600);
/* check only, do not modify
cellhd->north = 90.0 + cellhd->ns_res / 2.0;
lladjust = 1;
*/
}
}
else
G_fatal_error(_("Illegal latitude for North: %g"), cellhd->north);
}
/* south */
diff = (cellhd->south + 90) / cellhd->ns_res;
if (diff < 0)
diff = -diff;
if (cellhd->south > -90.0 && diff < 1.0) {
G_verbose_message(_("%g cells missing to reach 90 degree south"), diff);
if (diff < llepsilon && diff > fpepsilon) {
G_verbose_message(
_("Subtle input data rounding error of south boundary (%g)"),
cellhd->south + 90.0);
/* check only, do not modify
cellhd->south = -90.0;
lladjust = 1;
*/
}
}
if (cellhd->south < -90.0) {
if (diff <= 0.5 + llepsilon) {
G_important_message(_("90 degree south is exceeded by %g cells"),
diff);
if (diff < llepsilon && diff > fpepsilon) {
G_verbose_message(_("Subtle input data rounding error of south "
"boundary (%g)"),
cellhd->south + 90);
G_debug(1, "South of south in seconds: %g",
(-cellhd->south - 90) * 3600);
/* check only, do not modify
cellhd->south = -90.0;
lladjust = 1;
*/
}
diff = diff - 0.5;
if (diff < 0)
diff = -diff;
if (diff < llepsilon && diff > fpepsilon) {
G_verbose_message(_("Subtle input data rounding error of south "
"boundary (%g)"),
cellhd->south + 90 + cellhd->ns_res / 2.0);
G_debug(1, "South of south + 0.5 cells in seconds: %g",
(-cellhd->south - 90 - cellhd->ns_res / 2.0) * 3600);
/* check only, do not modify
cellhd->south = -90.0 - cellhd->ns_res / 2.0;
lladjust = 1;
*/
}
}
else
G_fatal_error(_("Illegal latitude for South: %g"), cellhd->south);
}
if (lladjust)
cellhd->ns_res = (cellhd->north - cellhd->south) / cellhd->rows;
return lladjust;
}
static int ll_check_ew(struct Cell_head *cellhd)
{
int lladjust;
double diff;
int ncells;
/* lat/lon checks */
if (cellhd->proj != PROJECTION_LL)
return 0;
lladjust = 0;
G_debug(3, "ll_check_ew: epsilon: %g", llepsilon);
/* west - east, no adjustment */
diff = (cellhd->east - cellhd->west) / cellhd->ew_res;
ncells = (int)(diff + 0.5);
diff -= ncells;
if ((diff < 0 && diff < -fpepsilon) || (diff > 0 && diff > fpepsilon)) {
G_verbose_message(
_("EW extent does not match EW resolution: %g cells difference"),
diff);
}
if (cellhd->east - cellhd->west > 360.0) {
diff = (cellhd->east - cellhd->west - 360.0) / cellhd->ew_res;
if (diff > fpepsilon)
G_important_message(_("360 degree EW extent is exceeded by %g cells"
" (East: %g, West: %g)"),
diff, cellhd->east, cellhd->west);
}
else if (cellhd->east - cellhd->west < 360.0) {
diff = (360.0 - (cellhd->east - cellhd->west)) / cellhd->ew_res;
if (diff < 1.0 && diff > fpepsilon)
G_verbose_message(
_("%g cells missing to cover 360 degree EW extent"), diff);
}
return lladjust;
}
/*!
* \brief Adjust window for lat/lon.
*
* This function tries to automatically fix fp precision issues and
* adjust rounding errors for lat/lon.
*
* <b>Note:</b> 3D values are not adjusted.
*
* \param[in,out] cellhd pointer to Cell_head structure
* \return 1 if window was adjusted
* \return 0 if window was not adjusted
*/
int G_adjust_window_ll(struct Cell_head *cellhd)
{
int ll_adjust, res_adj;
double dsec, dsec2;
char buf[100], buf2[100];
double diff;
double old, new;
struct Cell_head cellhds; /* everything in seconds, not degrees */
/* lat/lon checks */
if (cellhd->proj != PROJECTION_LL)
return 0;
/* put everything through ll_format + ll_scan */
G_llres_format(cellhd->ns_res, buf);
if (G_llres_scan(buf, &new) != 1)
G_fatal_error(_("Invalid NS resolution"));
cellhd->ns_res = new;
G_llres_format(cellhd->ew_res, buf);
if (G_llres_scan(buf, &new) != 1)
G_fatal_error(_("Invalid EW resolution"));
cellhd->ew_res = new;
G_lat_format(cellhd->north, buf);
if (G_lat_scan(buf, &new) != 1)
G_fatal_error(_("Invalid North"));
cellhd->north = new;
G_lat_format(cellhd->south, buf);
if (G_lat_scan(buf, &new) != 1)
G_fatal_error(_("Invalid South"));
cellhd->south = new;
G_lon_format(cellhd->west, buf);
if (G_lon_scan(buf, &new) != 1)
G_fatal_error(_("Invalid West"));
cellhd->west = new;
G_lon_format(cellhd->east, buf);
if (G_lon_scan(buf, &new) != 1)
G_fatal_error(_("Invalid East"));
cellhd->east = new;
/* convert to seconds */
cellhds = *cellhd;
old = cellhds.ns_res * 3600;
snprintf(buf, sizeof(buf), "%f", old);
sscanf(buf, "%lf", &new);
cellhds.ns_res = new;
old = cellhds.ew_res * 3600;
snprintf(buf, sizeof(buf), "%f", old);
sscanf(buf, "%lf", &new);
cellhds.ew_res = new;
old = cellhds.north * 3600;
snprintf(buf, sizeof(buf), "%f", old);
sscanf(buf, "%lf", &new);
cellhds.north = new;
old = cellhds.south * 3600;
snprintf(buf, sizeof(buf), "%f", old);
sscanf(buf, "%lf", &new);
cellhds.south = new;
old = cellhds.west * 3600;
snprintf(buf, sizeof(buf), "%f", old);
sscanf(buf, "%lf", &new);
cellhds.west = new;
old = cellhds.east * 3600;
snprintf(buf, sizeof(buf), "%f", old);
sscanf(buf, "%lf", &new);
cellhds.east = new;
ll_adjust = 0;
/* N - S */
/* resolution */
res_adj = 0;
old = cellhds.ns_res;
if (old > 0.4) {
/* round to nearest 0.1 sec */
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = fabs(dsec2 - dsec) / dsec;
if (diff > 0 && diff < llepsilon) {
G_llres_format(old / 3600, buf);
G_llres_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("NS resolution rounded from %s to %s"), buf,
buf2);
ll_adjust = 1;
res_adj = 1;
cellhds.ns_res = new;
}
}
if (res_adj) {
double n_off, s_off;
old = cellhds.north;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
diff = fabs(dsec2 - dsec) / (cellhds.ns_res * 10);
n_off = diff;
old = cellhds.south;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
diff = fabs(dsec2 - dsec) / (cellhds.ns_res * 10);
s_off = diff;
if (n_off < llepsilon || n_off <= s_off) {
old = cellhds.north;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = n_off;
if (diff > 0 && diff < llepsilon) {
G_lat_format(old / 3600, buf);
G_lat_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("North rounded from %s to %s"), buf,
buf2);
cellhds.north = new;
}
old = cellhds.south;
new = cellhds.north - cellhds.ns_res * cellhds.rows;
diff = fabs(new - old) / cellhds.ns_res;
if (diff > 0) {
G_lat_format(old / 3600, buf);
G_lat_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("South adjusted from %s to %s"), buf,
buf2);
}
cellhds.south = new;
}
else {
old = cellhds.south;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = s_off;
if (diff > 0 && diff < llepsilon) {
G_lat_format(old / 3600, buf);
G_lat_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("South rounded from %s to %s"), buf,
buf2);
cellhds.south = new;
}
old = cellhds.north;
new = cellhds.south + cellhds.ns_res * cellhds.rows;
diff = fabs(new - old) / cellhds.ns_res;
if (diff > 0) {
G_lat_format(old / 3600, buf);
G_lat_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("North adjusted from %s to %s"), buf,
buf2);
}
cellhds.north = new;
}
}
else {
old = cellhds.north;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = fabs(dsec2 - dsec) / (cellhds.ns_res * 10);
if (diff > 0 && diff < llepsilon) {
G_lat_format(old / 3600, buf);
G_lat_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("North rounded from %s to %s"), buf, buf2);
ll_adjust = 1;
cellhds.north = new;
}
old = cellhds.south;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = fabs(dsec2 - dsec) / (cellhds.ns_res * 10);
if (diff > 0 && diff < llepsilon) {
G_lat_format(old / 3600, buf);
G_lat_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("South rounded from %s to %s"), buf, buf2);
ll_adjust = 1;
cellhds.south = new;
}
}
cellhds.ns_res = (cellhds.north - cellhds.south) / cellhds.rows;
/* E - W */
/* resolution */
res_adj = 0;
old = cellhds.ew_res;
if (old > 0.4) {
/* round to nearest 0.1 sec */
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = fabs(dsec2 - dsec) / dsec;
if (diff > 0 && diff < llepsilon) {
G_llres_format(old / 3600, buf);
G_llres_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("EW resolution rounded from %s to %s"), buf,
buf2);
ll_adjust = 1;
res_adj = 1;
cellhds.ew_res = new;
}
}
if (res_adj) {
double w_off, e_off;
old = cellhds.west;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
diff = fabs(dsec2 - dsec) / (cellhds.ew_res * 10);
w_off = diff;
old = cellhds.east;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
diff = fabs(dsec2 - dsec) / (cellhds.ew_res * 10);
e_off = diff;
if (w_off < llepsilon || w_off <= e_off) {
old = cellhds.west;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = w_off;
if (diff > 0 && diff < llepsilon) {
G_lon_format(old / 3600, buf);
G_lon_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("West rounded from %s to %s"), buf,
buf2);
cellhds.west = new;
}
old = cellhds.east;
new = cellhds.west + cellhds.ew_res * cellhds.cols;
diff = fabs(new - old) / cellhds.ew_res;
if (diff > 0) {
G_lon_format(old / 3600, buf);
G_lon_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("East adjusted from %s to %s"), buf,
buf2);
}
cellhds.east = new;
}
else {
old = cellhds.east;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = e_off;
if (diff > 0 && diff < llepsilon) {
G_lon_format(old / 3600, buf);
G_lon_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("East rounded from %s to %s"), buf,
buf2);
cellhds.east = new;
}
old = cellhds.west;
new = cellhds.east - cellhds.ew_res * cellhds.cols;
diff = fabs(new - cellhds.west) / cellhds.ew_res;
if (diff > 0) {
G_lon_format(old / 3600, buf);
G_lon_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("West adjusted from %s to %s"), buf,
buf2);
}
cellhds.west = new;
}
}
else {
old = cellhds.west;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = fabs(dsec2 - dsec) / (cellhds.ew_res * 10);
if (diff > 0 && diff < llepsilon) {
G_lon_format(old / 3600, buf);
G_lon_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("West rounded from %s to %s"), buf, buf2);
ll_adjust = 1;
cellhds.west = new;
}
old = cellhds.east;
dsec = old * 10;
dsec2 = floor(dsec + 0.5);
new = dsec2 / 10;
diff = fabs(dsec2 - dsec) / (cellhds.ew_res * 10);
if (diff > 0 && diff < llepsilon) {
G_lon_format(old / 3600, buf);
G_lon_format(new / 3600, buf2);
if (strcmp(buf, buf2))
G_verbose_message(_("East rounded from %s to %s"), buf, buf2);
ll_adjust = 1;
cellhds.east = new;
}
}
cellhds.ew_res = (cellhds.east - cellhds.west) / cellhds.cols;
cellhd->ns_res = cellhds.ns_res / 3600;
cellhd->ew_res = cellhds.ew_res / 3600;
cellhd->north = cellhds.north / 3600;
cellhd->south = cellhds.south / 3600;
cellhd->west = cellhds.west / 3600;
cellhd->east = cellhds.east / 3600;
return ll_adjust;
}
G_adjust_Cell_head3
void G_adjust_Cell_head3(struct Cell_head *cellhd, int row_flag, int col_flag, int depth_flag)
Adjust cell header for 3D values.
Definition adj_cellhd.c:163
LL_TOLERANCE
#define LL_TOLERANCE
Definition adj_cellhd.c:19
G_adjust_Cell_head
void G_adjust_Cell_head(struct Cell_head *cellhd, int row_flag, int col_flag)
Adjust cell header.
Definition adj_cellhd.c:51
G_adjust_window_ll
int G_adjust_window_ll(struct Cell_head *cellhd)
Adjust window for lat/lon.
Definition adj_cellhd.c:552
G_debug
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition debug.c:66
G_verbose_message
void G_verbose_message(const char *msg,...)
Print a message to stderr but only if module is in verbose mode.
Definition gis/error.c:108
G_important_message
void G_important_message(const char *msg,...)
Print a message to stderr even in brief mode (verbosity=1).
Definition gis/error.c:130
G_fatal_error
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition gis/error.c:159
G_warning
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition gis/error.c:203
G_lat_format
void G_lat_format(double lat, char *buf)
Definition ll_format.c:40
G_llres_format
void G_llres_format(double res, char *buf)
Definition ll_format.c:70
G_lon_format
void G_lon_format(double lon, char *buf)
Definition ll_format.c:55
G_lat_scan
int G_lat_scan(const char *buf, double *lat)
Definition ll_scan.c:45
G_lon_scan
int G_lon_scan(const char *buf, double *lon)
Definition ll_scan.c:50
G_llres_scan
int G_llres_scan(const char *buf, double *res)
Definition ll_scan.c:55