25
26
#include <stdlib.h>
26
27
#include <string.h>
27
28
#include <grass/gis.h>
28
#include <grass/site.h>
29
#include <grass/raster.h>
30
#include <grass/vector.h>
31
#include <grass/dbmi.h>
29
32
#include <grass/glocale.h>
31
int centroids(int, int *, int *, int, int);
34
#include "local_proto.h"
33
36
int main(int argc, char *argv[])
36
CELL *data_buf, *clump_buf;
38
43
int row, col, rows, cols;
39
44
int out_mode, use_MASK, *n, *e;
41
46
int fd_data, fd_clump;
42
char buf[200], datamap[100], clumpmap[100], site_list[100];
43
char *curr_mapset, *data_mapset, *clump_mapset;
48
const char *datamap, *clumpmap, *centroidsmap;
44
50
double avg, vol, total_vol, east, north, *sum;
45
52
struct Cell_head window;
46
struct Map_info *fd_sites = NULL;
54
struct Map_info *fd_centroids;
55
struct line_pnts *Points;
56
struct line_cats *Cats;
57
struct field_info *Fi;
49
63
struct GModule *module;
50
struct Option *opt1, *opt2, *opt3;
65
struct Option *input, *clump, *centroids, *output;
71
/* define parameters and flags */
54
72
G_gisinit(argv[0]);
56
74
module = G_define_module();
57
module->keywords = _("raster");
59
_("Calculates the volume of data \"clumps\", "
60
"and (optionally) produces a GRASS vector points map "
61
"containing the calculated centroids of these clumps.");
63
opt1 = G_define_option();
65
opt1->type = TYPE_STRING;
67
opt1->gisprompt = "old,cell,raster";
69
_("Existing raster map representing data that will be summed within clumps");
71
opt2 = G_define_option();
73
opt2->type = TYPE_STRING;
75
opt2->gisprompt = "old,cell,raster";
77
_("Existing raster map, preferably the output of r.clump");
79
opt3 = G_define_option();
80
opt3->key = "centroids";
81
opt3->type = TYPE_STRING;
83
opt3->gisprompt = "new,vector,vector";
84
opt3->description = _("Vector points map to contain clump centroids");
86
flag1 = G_define_flag();
88
flag1->description = _("Generate unformatted report");
75
G_add_keyword(_("raster"));
76
G_add_keyword(_("volume"));
77
G_add_keyword(_("clumps"));
79
_("Calculates the volume of data \"clumps\".");
80
module->description = _("Optionally produces a GRASS vector points map "
81
"containing the calculated centroids of these clumps.");
83
opt.input = G_define_standard_option(G_OPT_R_INPUT);
84
opt.input->description =
85
_("Name of input raster map representing data that will be summed within clumps");
87
opt.clump = G_define_standard_option(G_OPT_R_INPUT);
88
opt.clump->key = "clump";
89
opt.clump->required = NO;
91
_("Name of input clump raster map");
92
opt.clump->description = _("Preferably the output of r.clump. "
93
"If no clump map is given than MASK is used.");
95
opt.centroids = G_define_standard_option(G_OPT_V_OUTPUT);
96
opt.centroids->key = "centroids";
97
opt.centroids->required = NO;
98
opt.centroids->description = _("Name for output vector points map to contain clump centroids");
100
opt.output = G_define_standard_option(G_OPT_F_OUTPUT);
101
opt.output->required = NO;
103
_("Name for output file to hold the report");
104
opt.output->description =
105
_("If no output file given report is printed to standard output");
107
flag.report = G_define_flag();
108
flag.report->key = 'f';
109
flag.report->description = _("Generate unformatted report (items separated by colon)");
90
111
if (G_parser(argc, argv))
91
112
exit(EXIT_FAILURE);
93
/* get current window */
94
G_get_window(&window);
98
out_mode = 1; /* assume full output text */
99
mysite = G_site_new_struct(CELL_TYPE, 2, 0, 4);
101
114
/* get arguments */
102
strcpy(datamap, opt1->answer);
104
if (opt2->answer != NULL)
105
strcpy(clumpmap, opt2->answer);
109
if (opt3->answer != NULL)
110
strcpy(site_list, opt3->answer);
114
out_mode = (!flag1->answer);
117
G_fatal_error(_("No data map specified"));
115
datamap = opt.input->answer;
118
if (opt.clump->answer)
119
clumpmap = opt.clump->answer;
126
if (opt.centroids->answer) {
127
centroidsmap = opt.centroids->answer;
128
fd_centroids = G_malloc(sizeof(struct Map_info));
131
out_mode = (!flag.report->answer);
120
* See if MASK or a separate "clumpmap" layer is to be used-- it must(!)
121
* be one of those two choices.
134
* see if MASK or a separate "clumpmap" raster map is to be used
135
* -- it must(!) be one of those two choices.
124
if (*clumpmap == '\0') {
125
strcpy(clumpmap, "MASK");
127
if (G_find_cell(clumpmap, G_mapset()) == NULL)
128
G_fatal_error(_("No clump map specified and MASK not set."));
130
curr_mapset = G_mapset();
131
data_mapset = G_find_cell2(datamap, "");
133
G_fatal_error(_("Unable to find data map"));
135
fd_data = G_open_cell_old(datamap, data_mapset);
137
clump_mapset = curr_mapset;
139
clump_mapset = G_find_cell2(clumpmap, "");
141
G_fatal_error(_("Unable to find clump map"));
143
fd_clump = G_open_cell_old(clumpmap, clump_mapset);
145
/* initialize sites file (for centroids) if needed */
147
fd_sites = G_fopen_sites_new(site_list);
148
if (fd_sites == NULL)
149
G_fatal_error(_("Unable to open centroids vector points map"));
141
if (!G_find_raster2(clumpmap, G_mapset()))
142
G_fatal_error(_("No MASK found. If no clump map is given than the MASK is required. "
143
"You need to define a clump raster map or create a MASK by r.mask command."));
144
G_important_message(_("No clump map given, using MASK"));
147
/* open input and clump raster maps */
148
fd_data = Rast_open_old(datamap, "");
149
fd_clump = Rast_open_old(clumpmap, use_MASK ? G_mapset() : "");
151
/* initialize vector map (for centroids) if needed */
153
if (Vect_open_new(fd_centroids, centroidsmap, WITHOUT_Z) < 0)
154
G_fatal_error(_("Unable to create vector map <%s>"), centroidsmap);
156
Points = Vect_new_line_struct();
157
Cats = Vect_new_cats_struct();
159
/* initialize data structures */
160
Vect_append_point(Points, 0., 0., 0.);
161
Vect_cat_set(Cats, 1, 1);
164
/* initialize output file */
165
if (opt.output->answer && strcmp(opt.output->answer, "-") != 0) {
166
if (freopen(opt.output->answer, "w", stdout) == NULL) {
167
perror(opt.output->answer);
152
172
/* initialize data accumulation arrays */
153
max = G_number_of_cats(clumpmap, clump_mapset);
173
max = Rast_get_max_c_cat(clumpmap, use_MASK ? G_mapset() : "");
155
175
sum = (double *)G_malloc((max + 1) * sizeof(double));
156
176
count = (long int *)G_malloc((max + 1) * sizeof(long int));
158
for (i = 0; i <= max; i++) {
163
data_buf = G_allocate_cell_buf();
164
clump_buf = G_allocate_cell_buf();
178
G_zero(sum, (max + 1) * sizeof(double));
179
G_zero(count, (max + 1) * sizeof(long int));
181
data_buf = Rast_allocate_d_buf();
182
clump_buf = Rast_allocate_c_buf();
166
184
/* get window size */
185
G_get_window(&window);
167
186
rows = window.rows;
168
187
cols = window.cols;
170
if (fd_data < 0 || fd_clump < 0)
171
G_fatal_error(_("Data or Clump file not open"));
173
189
/* now get the data -- first pass */
174
G_message("Complete ...");
175
190
for (row = 0; row < rows; row++) {
176
191
G_percent(row, rows, 2);
177
G_get_map_row(fd_data, data_buf, row);
178
G_get_map_row(fd_clump, clump_buf, row);
192
Rast_get_d_row(fd_data, data_buf, row);
193
Rast_get_c_row(fd_clump, clump_buf, row);
179
194
for (col = 0; col < cols; col++) {
180
195
i = clump_buf[col];
183
"Row=%d Col=%d Cat=%d in clump map [%s]; max=%d.\n",
184
row, col, i, clumpmap, max);
185
strcat(buf, "Cat value > max returned by G_number_of_cats.");
197
G_fatal_error(_("Invalid category value %d (max=%d): row=%d col=%d"),
200
G_debug(3, "row=%d col=%d: zero or negs ignored", row, col);
189
201
continue; /* ignore zeros and negs */
203
if (Rast_is_d_null_value(&data_buf[col])) {
204
G_debug(3, "row=%d col=%d: NULL ignored", row, col);
208
sum[i] += data_buf[col];
191
sum[i] += data_buf[col];
194
G_percent(row, rows, 2);
195
214
/* free some buffer space */
196
215
G_free(data_buf);
197
216
G_free(clump_buf);
203
222
i = centroids(fd_clump, e, n, 1, max);
224
/* close raster maps */
226
Rast_close(fd_clump);
205
228
/* got everything, now do output */
207
char desc[GNAME_MAX * 2 + 40];
209
site_info.form = NULL;
210
site_info.time = NULL;
211
site_info.stime = NULL;
212
sprintf(desc, "from %s on map %s using clumps from %s",
213
argv[0], datamap, clumpmap);
214
site_info.desc = G_store(desc);
215
site_info.name = G_store(site_list);
217
G_store("centroid east|centroid north|#cat vol avg t n");
218
G_site_put_head(fd_sites, &site_info);
230
G_message(_("Creating vector point map <%s>..."), centroidsmap);
232
sprintf(buf, _("From '%s' on raster map <%s> using clumps from <%s>"),
233
argv[0], datamap, clumpmap);
234
Vect_set_comment(fd_centroids, buf);
236
/* create attribute table */
237
Fi = Vect_default_field_info(fd_centroids, 1, NULL, GV_1TABLE);
239
driver = db_start_driver_open_database(Fi->driver,
240
Vect_subst_var(Fi->database, fd_centroids));
241
if (driver == NULL) {
242
G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
243
Vect_subst_var(Fi->database, fd_centroids), Fi->driver);
245
db_set_error_handler_driver(driver);
247
db_begin_transaction(driver);
249
db_init_string(&sql);
250
sprintf(buf, "create table %s (cat integer, volume double precision, "
251
"average double precision, sum double precision, count integer)",
253
db_set_string(&sql, buf);
254
Vect_map_add_dblink(fd_centroids, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
257
G_debug(3, "%s", db_get_string(&sql));
258
if (db_execute_immediate(driver, &sql) != DB_OK) {
259
G_fatal_error(_("Unable to create table: %s"), db_get_string(&sql));
221
fprintf(stdout, "Volume report on data from %s", datamap);
222
fprintf(stdout, " using clumps on %s map\n\n", clumpmap);
224
" Cat Average Data # Cells Centroid Total\n");
226
"Number in clump Total in clump Easting Northing Volume\n\n");
265
fprintf(stdout, _("\nVolume report on data from <%s> using clumps on <%s> raster map"),
267
fprintf(stdout, "\n\n");
269
_("Category Average Data # Cells Centroid Total\n"));
271
_("Number in clump Total in clump Easting Northing Volume"));
272
fprintf(stdout, "\n%s\n", SEP);
276
/* print output, write centroids */
230
277
for (i = 1; i <= max; i++) {
232
279
avg = sum[i] / (double)count[i];
234
281
total_vol += vol;
235
282
east = window.west + (e[i] + 0.5) * window.ew_res;
236
283
north = window.north - (n[i] + 0.5) * window.ns_res;
239
mysite->north = north;
241
mysite->dbl_att[0] = vol;
242
mysite->dbl_att[1] = avg;
243
mysite->dbl_att[2] = sum[i];
244
mysite->dbl_att[3] = (double)count[i];
245
/* "%-1.2f|%-1.2f|#%5d v=%-1.2f a=%-1.2f t=%-1.0f n=%ld\n", */
246
/* east, north, i, vol, avg, sum[i], count[i]); */
247
G_site_put(fd_sites, mysite);
284
if (fd_centroids) { /* write centroids if requested */
286
Points->y[0] = north;
288
Vect_write_line(fd_centroids, GV_POINT, Points, Cats);
290
sprintf(buf, "insert into %s values (%d, %f, %f, %f, %ld)",
291
Fi->table, i, vol, avg, sum[i], count[i]);
292
db_set_string(&sql, buf);
294
if (db_execute_immediate(driver, &sql) != DB_OK)
295
G_fatal_error(_("Cannot insert new row: %s"),
296
db_get_string(&sql));
251
"%5d%10.2f%10.0f %7ld %10.2f %10.2f %16.2f\n", i,
300
"%8d%10.2f%10.0f %7ld %10.2f %10.2f %16.2f\n", i,
252
301
avg, sum[i], count[i], east, north, vol);
254
303
fprintf(stdout, "%d:%.2f:%.0f:%ld:%.2f:%.2f:%.2f\n",
255
304
i, avg, sum[i], count[i], east, north, vol);
258
if (total_vol > 0.0 && out_mode)
259
fprintf(stdout, "%58s %14.2f", "Total Volume =", total_vol);
260
fprintf(stdout, "\n");
308
/* write centroid attributes and close the map*/
310
db_commit_transaction(driver);
311
Vect_close(fd_centroids);
314
/* print total value */
315
if (total_vol > 0.0 && out_mode) {
316
fprintf(stdout, "%s\n", SEP);
317
fprintf(stdout, "%60s = %14.2f", _("Total Volume"), total_vol);
318
fprintf(stdout, "\n");
261
321
exit(EXIT_SUCCESS);
262
} /* end of main() */