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