[GRASS-SVN] r54820 - grass/trunk/raster/r.neighbors
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Jan 30 08:34:52 PST 2013
Author: mmetz
Date: 2013-01-30 08:34:51 -0800 (Wed, 30 Jan 2013)
New Revision: 54820
Modified:
grass/trunk/raster/r.neighbors/gather.c
grass/trunk/raster/r.neighbors/local_proto.h
grass/trunk/raster/r.neighbors/main.c
grass/trunk/raster/r.neighbors/ncb.h
grass/trunk/raster/r.neighbors/null_cats.c
Log:
r.neighbors: support multiple methods and outputs
Modified: grass/trunk/raster/r.neighbors/gather.c
===================================================================
--- grass/trunk/raster/r.neighbors/gather.c 2013-01-30 15:43:36 UTC (rev 54819)
+++ grass/trunk/raster/r.neighbors/gather.c 2013-01-30 16:34:51 UTC (rev 54820)
@@ -45,52 +45,44 @@
ncb.mask[i][j] = ncb.weights[i][j] != 0;
}
-int gather(DCELL * values, int offset)
+int gather(DCELL *values, int offset)
{
int row, col;
int n = 0;
*values = 0;
- for (row = 0; row < ncb.nsize; row++)
+ for (row = 0; row < ncb.nsize; row++) {
for (col = 0; col < ncb.nsize; col++) {
- DCELL *c = &ncb.buf[row][offset + col];
if (ncb.mask && !ncb.mask[row][col])
continue;
- if (Rast_is_d_null_value(c))
- Rast_set_d_null_value(&values[n], 1);
- else
- values[n] = *c;
+ values[n] = ncb.buf[row][offset + col];
n++;
}
+ }
- return n ? n : -1;
+ return n;
}
-int gather_w(DCELL(*values)[2], int offset)
+int gather_w(DCELL *values, DCELL (*values_w)[2], int offset)
{
int row, col;
int n = 0;
- values[0][0] = 0;
- values[0][1] = 1;
+ values_w[0][0] = 0;
+ values_w[0][1] = 1;
- for (row = 0; row < ncb.nsize; row++)
+ for (row = 0; row < ncb.nsize; row++) {
for (col = 0; col < ncb.nsize; col++) {
- DCELL *c = &ncb.buf[row][offset + col];
+ values[n] = values_w[n][0] = ncb.buf[row][offset + col];
+ values_w[n][1] = ncb.weights[row][col];
- if (Rast_is_d_null_value(c))
- Rast_set_d_null_value(&values[n][0], 1);
- else
- values[n][0] = *c;
-
- values[n][1] = ncb.weights[row][col];
-
n++;
}
+ }
- return n ? n : -1;
+ return n;
}
Modified: grass/trunk/raster/r.neighbors/local_proto.h
===================================================================
--- grass/trunk/raster/r.neighbors/local_proto.h 2013-01-30 15:43:36 UTC (rev 54819)
+++ grass/trunk/raster/r.neighbors/local_proto.h 2013-01-30 16:34:51 UTC (rev 54820)
@@ -6,7 +6,7 @@
extern void circle_mask(void);
extern void weights_mask(void);
extern int gather(DCELL *, int);
-extern int gather_w(DCELL(*)[2], int);
+extern int gather_w(DCELL *, DCELL(*)[2], int);
/* readcell.c */
extern int readcell(int, int, int, int);
@@ -18,7 +18,7 @@
extern int intr_cats(void);
/* null_cats.c */
-extern int null_cats(void);
+extern int null_cats(const char *);
/* read_weights.c */
extern void read_weights(const char *);
Modified: grass/trunk/raster/r.neighbors/main.c
===================================================================
--- grass/trunk/raster/r.neighbors/main.c 2013-01-30 15:43:36 UTC (rev 54819)
+++ grass/trunk/raster/r.neighbors/main.c 2013-01-30 16:34:51 UTC (rev 54820)
@@ -68,27 +68,48 @@
struct ncb ncb;
+struct output
+{
+ const char *name;
+ char title[1024];
+ int fd;
+ DCELL *buf;
+ stat_func *method_fn;
+ stat_func_w *method_fn_w;
+ int copycolr;
+ int half;
+ ifunc cat_names;
+ int map_type;
+ double quantile;
+};
+
+static int find_method(const char *method_name)
+{
+ int i;
+
+ for (i = 0; menu[i].name; i++)
+ if (strcmp(menu[i].name, method_name) == 0)
+ return i;
+
+ G_fatal_error(_("Unknown method <%s>"), method_name);
+
+ return -1;
+}
+
int main(int argc, char *argv[])
{
char *p;
- int method;
int in_fd;
int selection_fd;
- int out_fd;
- DCELL *result;
+ int num_outputs;
+ struct output *outputs = NULL;
+ int copycolr, weights, have_weights_mask;
char *selection;
RASTER_MAP_TYPE map_type;
int row, col;
int readrow;
int nrows, ncols;
- int n;
- int copycolr;
- int half;
- stat_func *newvalue;
- stat_func_w *newvalue_w;
- ifunc cat_names;
- double quantile;
- const void *closure;
+ int i, n;
struct Colors colr;
struct Cell_head cellhd;
struct Cell_head window;
@@ -109,8 +130,9 @@
} flag;
DCELL *values; /* list of neighborhood values */
-
+ DCELL *values_tmp; /* list of neighborhood values */
DCELL(*values_w)[2]; /* list of neighborhood values and weights */
+ DCELL(*values_w_tmp)[2]; /* list of neighborhood values and weights */
G_gisinit(argv[0]);
@@ -133,6 +155,7 @@
parm.selection->description = _("Name of an input raster map to select the cells which should be processed");
parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
+ parm.output->multiple = YES;
parm.method = G_define_option();
parm.method->key = "method";
@@ -149,6 +172,7 @@
}
parm.method->options = p;
parm.method->description = _("Neighborhood operation");
+ parm.method->multiple = YES;
parm.method->guisection = _("Neighborhood");
parm.size = G_define_option();
@@ -181,6 +205,7 @@
parm.quantile->key = "quantile";
parm.quantile->type = TYPE_DOUBLE;
parm.quantile->required = NO;
+ parm.quantile->multiple = YES;
parm.quantile->description = _("Quantile to calculate for method=quantile");
parm.quantile->options = "0.0-1.0";
parm.quantile->answer = "0.5";
@@ -211,7 +236,6 @@
G_fatal_error(_("weight= and gauss= are mutually exclusive"));
ncb.oldcell = parm.input->answer;
- ncb.newcell = parm.output->answer;
if (!flag.align->answer) {
Rast_get_cellhd(ncb.oldcell, "", &cellhd);
@@ -227,30 +251,88 @@
in_fd = Rast_open_old(ncb.oldcell, "");
map_type = Rast_get_map_type(in_fd);
- /* get the method */
- for (method = 0; (p = menu[method].name); method++)
- if ((strcmp(p, parm.method->answer) == 0))
- break;
- if (!p) {
- G_warning(_("<%s=%s> unknown %s"),
- parm.method->key, parm.method->answer, parm.method->key);
- G_usage();
- exit(EXIT_FAILURE);
- }
+ /* process the output maps */
+ for (i = 0; parm.output->answers[i]; i++)
+ ;
+ num_outputs = i;
- if (menu[method].method == c_quant) {
- quantile = atoi(parm.quantile->answer);
- closure = &quantile;
+ for (i = 0; parm.method->answers[i]; i++)
+ ;
+ if (num_outputs != i)
+ G_fatal_error(_("output= and method= must have the same number of values"));
+
+ outputs = G_calloc(num_outputs, sizeof(struct output));
+
+ /* read the weights */
+ weights = 0;
+ ncb.weights = NULL;
+ ncb.mask = NULL;
+ if (parm.weight->answer) {
+ read_weights(parm.weight->answer);
+ weights = 1;
}
+ else if (parm.gauss->answer) {
+ gaussian_weights(atof(parm.gauss->answer));
+ weights = 1;
+ }
+
+ copycolr = 0;
+ have_weights_mask = 0;
- half = (map_type == CELL_TYPE) ? menu[method].half : 0;
+ for (i = 0; i < num_outputs; i++) {
+ struct output *out = &outputs[i];
+ const char *output_name = parm.output->answers[i];
+ const char *method_name = parm.method->answers[i];
+ int method = find_method(method_name);
- /* establish the newvalue routine */
- newvalue = menu[method].method;
- newvalue_w = menu[method].method_w;
+ out->name = output_name;
+ if (weights) {
+ if (menu[method].method_w) {
+ out->method_fn = NULL;
+ out->method_fn_w = menu[method].method_w;
+ }
+ else {
+ if (parm.weight->answer) {
+ G_warning(_("Method %s not compatible with weighing window, using weight mask instead"),
+ method_name);
+ if (!have_weights_mask) {
+ weights_mask();
+ have_weights_mask = 1;
+ }
+ }
+ else if (parm.gauss->answer) {
+ G_warning(_("Method %s not compatible with Gaussian filter, using unweighed version instead"),
+ method_name);
+ }
+
+ out->method_fn = menu[method].method;
+ out->method_fn_w = NULL;
+ }
+ }
+ else {
+ out->method_fn = menu[method].method;
+ out->method_fn_w = NULL;
+ }
+ out->half = menu[method].half;
+ out->copycolr = menu[method].copycolr;
+ out->cat_names = menu[method].cat_names;
+ if (out->copycolr)
+ copycolr = 1;
+ out->quantile = (parm.quantile->answer && parm.quantile->answers[i])
+ ? atof(parm.quantile->answers[i])
+ : 0;
+ out->buf = Rast_allocate_d_buf();
+ out->fd = Rast_open_new(output_name, DCELL_TYPE);
+ /* get title, initialize the category and stat info */
+ if (parm.title->answer)
+ strcpy(out->title, parm.title->answer);
+ else
+ sprintf(out->title, "%dx%d neighborhood: %s of %s",
+ ncb.nsize, ncb.nsize, menu[method].name, ncb.oldcell);
+ }
+
/* copy color table? */
- copycolr = menu[method].copycolr;
if (copycolr) {
G_suppress_warnings(1);
copycolr =
@@ -258,34 +340,10 @@
G_suppress_warnings(0);
}
- /* read the weights */
- if (parm.weight->answer) {
- read_weights(parm.weight->answer);
- if (!newvalue_w)
- weights_mask();
- }
- else if (parm.gauss->answer) {
- if (!newvalue_w)
- G_fatal_error(_("Method %s not compatible with Gaussian filter"), parm.method->answer);
- gaussian_weights(atof(parm.gauss->answer));
- }
- else
- newvalue_w = NULL;
-
/* allocate the cell buffers */
allocate_bufs();
- result = Rast_allocate_d_buf();
- /* get title, initialize the category and stat info */
- if (parm.title->answer)
- strcpy(ncb.title, parm.title->answer);
- else
- sprintf(ncb.title, "%dx%d neighborhood: %s of %s",
- ncb.nsize, ncb.nsize, menu[method].name, ncb.oldcell);
-
-
/* initialize the cell bufs with 'dist' rows of the old cellfile */
-
readrow = 0;
for (row = 0; row < ncb.dist; row++)
readcell(in_fd, readrow++, nrows, ncols);
@@ -300,17 +358,19 @@
selection = NULL;
}
- /*open the new raster map */
- out_fd = Rast_open_new(ncb.newcell, map_type);
-
if (flag.circle->answer)
circle_mask();
- if (newvalue_w)
+ values_w = NULL;
+ values_w_tmp = NULL;
+ if (weights) {
values_w =
(DCELL(*)[2]) G_malloc(ncb.nsize * ncb.nsize * 2 * sizeof(DCELL));
- else
- values = (DCELL *) G_malloc(ncb.nsize * ncb.nsize * sizeof(DCELL));
+ values_w_tmp =
+ (DCELL(*)[2]) G_malloc(ncb.nsize * ncb.nsize * 2 * sizeof(DCELL));
+ }
+ values = (DCELL *) G_malloc(ncb.nsize * ncb.nsize * sizeof(DCELL));
+ values_tmp = (DCELL *) G_malloc(ncb.nsize * ncb.nsize * sizeof(DCELL));
for (row = 0; row < nrows; row++) {
G_percent(row, nrows, 2);
@@ -320,57 +380,73 @@
Rast_get_null_value_row(selection_fd, selection, row);
for (col = 0; col < ncols; col++) {
- DCELL *rp = &result[col];
if (selection && selection[col]) {
/* ncb.buf length is region row length + 2 * ncb.dist (eq. floor(neighborhood/2))
* Thus original data start is shifted by ncb.dist! */
- *rp = ncb.buf[ncb.dist][col+ncb.dist];
+ for (i = 0; i < num_outputs; i++)
+ outputs[i].buf[col] = ncb.buf[ncb.dist][col + ncb.dist];
continue;
}
- if (newvalue_w)
- n = gather_w(values_w, col);
+ if (weights)
+ n = gather_w(values, values_w, col);
else
n = gather(values, col);
- if (n < 0)
- Rast_set_d_null_value(rp, 1);
- else {
- if (newvalue_w)
- newvalue_w(rp, values_w, n, closure);
- else
- newvalue(rp, values, n, closure);
+ for (i = 0; i < num_outputs; i++) {
+ struct output *out = &outputs[i];
+ DCELL *rp = &out->buf[col];
- if (half && !Rast_is_d_null_value(rp))
- *rp += 0.5;
+ if (n == 0) {
+ Rast_set_d_null_value(rp, 1);
+ }
+ else {
+ if (out->method_fn_w) {
+ memcpy(values_w_tmp, values_w, n * 2 * sizeof(DCELL));
+ (*out->method_fn_w)(rp, values_w_tmp, n, &out->quantile);
+ }
+ else {
+ memcpy(values_tmp, values, n * sizeof(DCELL));
+ (*out->method_fn)(rp, values_tmp, n, &out->quantile);
+ }
+
+ if (out->half && !Rast_is_d_null_value(rp))
+ *rp += 0.5;
+ }
}
}
- Rast_put_d_row(out_fd, result);
+ for (i = 0; i < num_outputs; i++) {
+ struct output *out = &outputs[i];
+
+ Rast_put_d_row(out->fd, out->buf);
+ }
}
G_percent(row, nrows, 2);
- Rast_close(out_fd);
Rast_close(in_fd);
if (selection)
Rast_close(selection_fd);
- /* put out category info */
- null_cats();
- if ((cat_names = menu[method].cat_names))
- cat_names();
+ for (i = 0; i < num_outputs; i++) {
+ Rast_close(outputs[i].fd);
- Rast_write_cats(ncb.newcell, &ncb.cats);
+ /* put out category info */
+ null_cats(outputs[i].title);
+ if (outputs[i].cat_names)
+ outputs[i].cat_names();
- if (copycolr)
- Rast_write_colors(ncb.newcell, G_mapset(), &colr);
+ Rast_write_cats(outputs[i].name, &ncb.cats);
- Rast_short_history(ncb.newcell, "raster", &history);
- Rast_command_history(&history);
- Rast_write_history(ncb.newcell, &history);
+ if (copycolr && outputs[i].copycolr)
+ Rast_write_colors(outputs[i].name, G_mapset(), &colr);
+ Rast_short_history(outputs[i].name, "raster", &history);
+ Rast_command_history(&history);
+ Rast_write_history(outputs[i].name, &history);
+ }
exit(EXIT_SUCCESS);
}
Modified: grass/trunk/raster/r.neighbors/ncb.h
===================================================================
--- grass/trunk/raster/r.neighbors/ncb.h 2013-01-30 15:43:36 UTC (rev 54819)
+++ grass/trunk/raster/r.neighbors/ncb.h 2013-01-30 16:34:51 UTC (rev 54820)
@@ -7,12 +7,9 @@
int nsize; /* size of the neighborhood */
int dist; /* nsize/2 */
struct Categories cats;
- char title[1024];
- FILE *out;
char **mask;
DCELL **weights;
const char *oldcell;
- const char *newcell;
};
extern struct ncb ncb;
Modified: grass/trunk/raster/r.neighbors/null_cats.c
===================================================================
--- grass/trunk/raster/r.neighbors/null_cats.c 2013-01-30 15:43:36 UTC (rev 54819)
+++ grass/trunk/raster/r.neighbors/null_cats.c 2013-01-30 16:34:51 UTC (rev 54820)
@@ -2,9 +2,9 @@
#include <grass/raster.h>
#include "ncb.h"
-int null_cats(void)
+int null_cats(const char *title)
{
- Rast_init_cats(ncb.title, &ncb.cats);
+ Rast_init_cats(title, &ncb.cats);
return 0;
}
More information about the grass-commit
mailing list