1
2 /****************************************************************************
3 *
4 * MODULE: r.patch
5 * AUTHOR(S): Michael Shapiro, CERL (original contributor),
6 * Hamish Bowman <hamish_b yahoo.com>,
7 * Markus Neteler <neteler itc.it>,
8 * Glynn Clements <glynn gclements.plus.com>,
9 * Jachym Cepicky <jachym les-ejk.cz>,
10 * Jan-Oliver Wagner <jan intevation.de>,
11 * Huidae Cho <grass4u gmail.com>
12 * PURPOSE:
13 * COPYRIGHT: (C) 1999-2014 by the GRASS Development Team
14 *
15 * This program is free software under the GNU General Public
16 * License (>=v2). Read the file COPYING that comes with GRASS
17 * for details.
18 *
19 *****************************************************************************/
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <grass/gis.h>
23 #include <grass/raster.h>
24 #include <grass/glocale.h>
25 #include "local_proto.h"
26
main(int argc,char * argv[])27 int main(int argc, char *argv[])
28 {
29 int *infd;
30 struct Categories cats;
31 struct Cell_stats *statf;
32 struct Colors colr;
33 int cats_ok;
34 int colr_ok;
35 int outfd;
36 RASTER_MAP_TYPE out_type, map_type;
37 size_t out_cell_size;
38 struct History history;
39 void *presult, *patch;
40 int nfiles;
41 char *rname;
42 int i;
43 int row, nrows, ncols;
44 int use_zero, no_support;
45 char *new_name;
46 char **names;
47 char **ptr;
48 struct Cell_head window;
49 struct Cell_head *cellhd;
50
51 struct GModule *module;
52 struct Flag *zeroflag, *nosupportflag;
53 struct Option *opt1, *opt2;
54
55 G_gisinit(argv[0]);
56
57 module = G_define_module();
58 G_add_keyword(_("raster"));
59 G_add_keyword(_("geometry"));
60 G_add_keyword(_("mosaicking"));
61 G_add_keyword(_("merge"));
62 G_add_keyword(_("patching"));
63 G_add_keyword(_("aggregation"));
64 G_add_keyword(_("series"));
65 module->description =
66 _("Creates a composite raster map layer by using "
67 "known category values from one (or more) map layer(s) "
68 "to fill in areas of \"no data\" in another map layer.");
69
70 /* Define the different options */
71
72 opt1 = G_define_standard_option(G_OPT_R_INPUTS);
73 opt1->description = _("Name of raster maps to be patched together");
74
75 opt2 = G_define_standard_option(G_OPT_R_OUTPUT);
76 opt2->description = _("Name for resultant raster map");
77
78 /* Define the different flags */
79
80 zeroflag = G_define_flag();
81 zeroflag->key = 'z';
82 zeroflag->description =
83 _("Use zero (0) for transparency instead of NULL");
84
85 nosupportflag = G_define_flag();
86 nosupportflag->key = 's';
87 nosupportflag->description =
88 _("Do not create color and category files");
89
90 if (G_parser(argc, argv))
91 exit(EXIT_FAILURE);
92
93 use_zero = (zeroflag->answer);
94 no_support = (nosupportflag->answer);
95
96 names = opt1->answers;
97
98 out_type = CELL_TYPE;
99
100 for (ptr = names, nfiles = 0; *ptr != NULL; ptr++, nfiles++) ;
101
102 if (nfiles < 2)
103 G_fatal_error(_("The minimum number of input raster maps is two"));
104
105 infd = G_malloc(nfiles * sizeof(int));
106 statf = G_malloc(nfiles * sizeof(struct Cell_stats));
107 cellhd = G_malloc(nfiles * sizeof(struct Cell_head));
108
109 for (i = 0; i < nfiles; i++) {
110 const char *name = names[i];
111 int fd;
112
113 fd = Rast_open_old(name, "");
114
115 infd[i] = fd;
116
117 map_type = Rast_get_map_type(fd);
118 if (map_type == FCELL_TYPE && out_type == CELL_TYPE)
119 out_type = FCELL_TYPE;
120 else if (map_type == DCELL_TYPE)
121 out_type = DCELL_TYPE;
122
123 Rast_init_cell_stats(&statf[i]);
124
125 Rast_get_cellhd(name, "", &cellhd[i]);
126 }
127
128 out_cell_size = Rast_cell_size(out_type);
129
130 rname = opt2->answer;
131 outfd = Rast_open_new(new_name = rname, out_type);
132
133 presult = Rast_allocate_buf(out_type);
134 patch = Rast_allocate_buf(out_type);
135
136 Rast_get_window(&window);
137 nrows = Rast_window_rows();
138 ncols = Rast_window_cols();
139
140 G_verbose_message(_("Percent complete..."));
141 for (row = 0; row < nrows; row++) {
142 double north_edge, south_edge;
143
144 G_percent(row, nrows, 2);
145 Rast_get_row(infd[0], presult, row, out_type);
146
147 north_edge = Rast_row_to_northing(row, &window);
148 south_edge = north_edge - window.ns_res;
149
150 if (out_type == CELL_TYPE)
151 Rast_update_cell_stats((CELL *) presult, ncols, &statf[0]);
152 for (i = 1; i < nfiles; i++) {
153 /* check if raster i overlaps with the current row */
154 if (south_edge >= cellhd[i].north ||
155 north_edge <= cellhd[i].south ||
156 window.west >= cellhd[i].east ||
157 window.east <= cellhd[i].west)
158 continue;
159
160 Rast_get_row(infd[i], patch, row, out_type);
161 if (!do_patch
162 (presult, patch, &statf[i], ncols, out_type, out_cell_size,
163 use_zero))
164 break;
165 }
166 Rast_put_row(outfd, presult, out_type);
167 }
168 G_percent(row, nrows, 2);
169
170 G_free(patch);
171 G_free(presult);
172 for (i = 0; i < nfiles; i++)
173 Rast_close(infd[i]);
174
175 if(!no_support) {
176 /*
177 * build the new cats and colors. do this before closing the new
178 * file, in case the new file is one of the patching files as well.
179 */
180 G_verbose_message(_("Creating support files for raster map <%s>..."), new_name);
181 support(names, statf, nfiles, &cats, &cats_ok, &colr, &colr_ok, out_type);
182 }
183
184 /* now close (and create) the result */
185 Rast_close(outfd);
186 if(!no_support) {
187 if (cats_ok)
188 Rast_write_cats(new_name, &cats);
189 if (colr_ok)
190 Rast_write_colors(new_name, G_mapset(), &colr);
191 }
192
193 Rast_short_history(new_name, "raster", &history);
194 Rast_command_history(&history);
195 Rast_write_history(new_name, &history);
196
197 exit(EXIT_SUCCESS);
198 }
199