1 
2 /***************************************************************************
3 *
4 * MODULE:    r.buffer
5 *
6 * AUTHOR(S): Michael Shapiro, US Army Construction Engineering Research Laboratory
7 *	     James Westervelt, US Army CERL
8 *
9 * PURPOSE:   This program creates distance zones from non-zero
10 *	     cells in a grid layer. Distances are specified in
11 *	     meters (on the command-line). Window does not have to
12 *	     have square cells. Works both for planimetric (UTM,
13 *	     State Plane) and lat-long.
14 *
15 * COPYRIGHT: (c) 2006 by the GRASS Development Team
16 *
17 *	     This program is free software under the GNU General Public
18 *	     License (>=v2). Read the file COPYING that comes with GRASS
19 *	     for details.
20 *
21 **************************************************************************/
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "distance.h"
28 #include "local_proto.h"
29 #include <grass/raster.h>
30 #include <grass/glocale.h>
31 
32 struct Distance *distances;
33 int ndist;
34 int wrap_ncols;
35 MAPTYPE *map;
36 struct Cell_head window;
37 int minrow, maxrow, mincol, maxcol;
38 char *pgm_name;
39 double meters_to_grid = 1.0;
40 double ns_to_ew_squared;
41 int count_rows_with_data;
42 
main(int argc,char * argv[])43 int main(int argc, char *argv[])
44 {
45     struct Distance *pd;
46     const char *input, *output, *mapset;
47     char **zone_list;
48     double to_meters;
49     const char *units;
50     int offset;
51     int count;
52     int step, nsteps;
53     struct History hist;
54 
55     struct GModule *module;
56     struct Option *opt1, *opt2, *opt3, *opt4;
57     struct Flag *flag2;
58     int ZEROFLAG;
59 
60     /* initialize GRASS */
61     G_gisinit(argv[0]);
62 
63     pgm_name = argv[0];
64 
65     module = G_define_module();
66     G_add_keyword(_("raster"));
67     G_add_keyword(_("buffer"));
68     module->description =
69 	_("Creates a raster map showing buffer zones "
70 	  "surrounding cells that contain non-NULL category values.");
71 
72     opt1 = G_define_standard_option(G_OPT_R_INPUT);
73 
74     opt2 = G_define_standard_option(G_OPT_R_OUTPUT);
75 
76     opt3 = G_define_option();
77     opt3->key = "distances";
78     opt3->type = TYPE_DOUBLE;
79     opt3->required = YES;
80     opt3->multiple = YES;
81     opt3->description = _("Distance zone(s)");
82 
83     opt4 = G_define_option();
84     opt4->key = "units";
85     opt4->options = "meters,kilometers,feet,miles,nautmiles";
86     opt4->type = TYPE_STRING;
87     opt4->required = NO;
88     opt4->description = _("Units of distance");
89     opt4->answer = "meters";
90 
91     flag2 = G_define_flag();
92     flag2->key = 'z';
93     flag2->description =
94 	_("Ignore zero (0) data cells instead of NULL cells");
95 
96     if (G_parser(argc, argv))
97 	exit(EXIT_FAILURE);
98 
99     init_grass();
100 
101     /* get input, output map names */
102     input = opt1->answer;
103     output = opt2->answer;
104     zone_list = opt3->answers;
105     units = opt4->answer;
106 
107     ZEROFLAG = 0;		/* default: use NULL for non-data cells */
108     ZEROFLAG = (flag2->answer);
109 
110     mapset = G_find_raster2(input, "");
111     if (mapset == NULL)
112 	G_fatal_error(_("Raster map <%s> not found"), input);
113 
114     /* parse units */
115     if (opt4->answer == NULL)
116 	units = "meters";
117 
118     if (strcmp(units, "meters") == 0)
119 	to_meters = 1.0;
120     else if (strcmp(units, "feet") == 0)
121 	to_meters = FEET_TO_METERS;
122     else if (strcmp(units, "kilometers") == 0)
123 	to_meters = KILOMETERS_TO_METERS;
124     else if (strcmp(units, "miles") == 0)
125 	to_meters = MILES_TO_METERS;
126     else if (strcmp(units, "nautmiles") == 0)
127 	to_meters = NAUT_MILES_TO_METERS;
128 
129     /* parse distances */
130     if (!(count = parse_distances(zone_list, to_meters)))
131 	G_fatal_error(_("Parse distances error"));
132 
133 
134     /* need to keep track of distance zones - in memory.
135      * process MAX_DIST at a time
136      *
137      * Coding: 0 == not-yet determined, 1 == input cells,
138      *         2 == distance zone #1,   3 == distance zone #2, etc.
139      */
140 
141     read_input_map(input, mapset, ZEROFLAG);
142 
143     offset = 0;
144 
145     nsteps = (count - 1) / MAX_DIST + 1;
146 
147     pd = distances;
148     for (step = 1; count > 0; step++) {
149 	if (nsteps > 1)
150 	    G_message(_("Pass %d (of %d)"), step, nsteps);
151 	ndist = count;
152 	if (ndist > MAX_DIST)
153 	    ndist = MAX_DIST;
154 	if (count_rows_with_data > 0)
155 	    execute_distance();
156 	write_output_map(output, offset);
157 	offset += ndist;
158 	distances += ndist;
159 	count -= ndist;
160     }
161     distances = pd;
162     make_support_files(output, units);
163 
164     /* write map history (meta data) */
165     Rast_short_history(output, "raster", &hist);
166     Rast_set_history(&hist, HIST_DATSRC_1, input);
167     Rast_append_format_history(&hist, "Buffer distance%s:", ndist > 1 ? "s" : "");
168     Rast_append_format_history(&hist, " %s %s", opt3->answer, units);
169     Rast_command_history(&hist);
170     Rast_write_history(output, &hist);
171 
172 
173     exit(EXIT_SUCCESS);
174 }
175