GRASS 8 Programmer's Manual  8.5.0dev(2025)-c070206eb1
group.c
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * MODULE: imagery library
4  * AUTHOR(S): Original author(s) name(s) unknown - written by CERL
5  * PURPOSE: Image processing library
6  * COPYRIGHT: (C) 1999, 2005 by the GRASS Development Team
7  *
8  * This program is free software under the GNU General Public
9  * License (>=v2). Read the file COPYING that comes with GRASS
10  * for details.
11  *
12  *****************************************************************************/
13 
14 /**********************************************************
15  * I_get_group (group);
16  * I_put_group (group);
17  *
18  * I_get_group_ref (group, &Ref);
19  * I_put_group_ref (group, &Ref);
20  * I_get_subgroup_ref_file (group, subgroup, &Ref);
21  * I_put_subgroup_ref_file (group, subgroup, &Ref);
22  * I_add_file_to_group_ref (name, mapset, &Ref)
23  * I_transfer_group_ref_file (&Src_ref, n, &Dst_ref)
24  * I_init_group_ref (&Ref);
25  * I_free_group_ref (&Ref);
26  **********************************************************/
27 
28 #include <string.h>
29 #include <stdlib.h>
30 #include <grass/imagery.h>
31 
32 static int get_ref(const char *, const char *, const char *, struct Ref *);
33 static int set_color(const char *, const char *, const char *, struct Ref *);
34 static int put_ref(const char *, const char *, const struct Ref *);
35 
36 /* get current group name from file GROUPFILE in current mapset */
37 int I_get_group(char *group)
38 {
39  FILE *fd;
40  int stat;
41 
42  *group = 0;
44  fd = G_fopen_old("", GROUPFILE, G_mapset());
46  if (fd == NULL)
47  return 0;
48  stat = (fscanf(fd, "%255s", group) == 1);
49  fclose(fd);
50  return stat;
51 }
52 
53 /* write group name to file GROUPFILE in current mapset */
54 int I_put_group(const char *group)
55 {
56  FILE *fd;
57 
58  fd = G_fopen_new("", GROUPFILE);
59  if (fd == NULL)
60  return 0;
61  fprintf(fd, "%s\n", group);
62  fclose(fd);
63  return 1;
64 }
65 
66 /* get current subgroup for group in current mapset */
67 int I_get_subgroup(const char *group, char *subgroup)
68 {
69  FILE *fd;
70  int stat;
71 
72  *subgroup = 0;
73  if (!I_find_group(group))
74  return 0;
78  if (fd == NULL)
79  return 0;
80  stat = (fscanf(fd, "%255s", subgroup) == 1);
81  fclose(fd);
82  return stat;
83 }
84 
85 /* write current subgroup to group in current mapset */
86 int I_put_subgroup(const char *group, const char *subgroup)
87 {
88  FILE *fd;
89 
90  if (!I_find_group(group))
91  return 0;
93  if (fd == NULL)
94  return 0;
95  fprintf(fd, "%s\n", subgroup);
96  fclose(fd);
97  return 1;
98 }
99 
100 /*!
101  * \brief read group REF file
102  *
103  * Reads the contents of the REF file for the specified <b>group</b> into
104  * the <b>ref</b> structure.
105  * Returns 1 if successful; 0 otherwise (but no error messages are printed).
106  *
107  * \param group
108  * \param ref
109  * \return int
110  */
111 int I_get_group_ref(const char *group, struct Ref *ref)
112 {
113  return get_ref(group, "", NULL, ref);
114 }
115 
116 /*!
117  * \brief read group REF file
118  *
119  * Reads the contents of the REF file for the specified <b>group</b> into
120  * the <b>ref</b> structure.
121  * Returns 1 if successful; 0 otherwise (but no error messages are printed).
122  *
123  * \param group
124  * \param mapset
125  * \param ref
126  * \return int
127  */
128 int I_get_group_ref2(const char *group, const char *mapset, struct Ref *ref)
129 {
130  return get_ref(group, "", mapset, ref);
131 }
132 
133 /*!
134  * \brief read subgroup REF file
135  *
136  * Reads the contents of the REF file for the
137  * specified <b>subgroup</b> of the specified <b>group</b> into the
138  * <b>ref</b> structure.
139  * Returns 1 if successful; 0 otherwise (but no error messages are printed).
140  *
141  * \param group
142  * \param subgroup
143  * \param ref
144  * \return int
145  */
146 int I_get_subgroup_ref(const char *group, const char *subgroup, struct Ref *ref)
147 {
148  return get_ref(group, subgroup, NULL, ref);
149 }
150 
151 /*!
152  * \brief read subgroup REF file
153  *
154  * Reads the contents of the REF file for the
155  * specified <b>subgroup</b> of the specified <b>group</b> into the
156  * <b>ref</b> structure.
157  * Returns 1 if successful; 0 otherwise (but no error messages are printed).
158  *
159  * \param group
160  * \param subgroup
161  * \param mapset
162  * \param ref
163  * \return int
164  */
165 int I_get_subgroup_ref2(const char *group, const char *subgroup,
166  const char *mapset, struct Ref *ref)
167 {
168  return get_ref(group, subgroup, mapset, ref);
169 }
170 
171 static int get_ref(const char *group, const char *subgroup, const char *gmapset,
172  struct Ref *ref)
173 {
174  char buf[1024];
175  char name[INAME_LEN], mapset[INAME_LEN];
176  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
177  char color[20];
178  FILE *fd;
179 
180  I_init_group_ref(ref);
181 
182  G_unqualified_name(group, gmapset, xname, xmapset);
183  group = xname;
184  gmapset = xmapset;
185 
186  if (gmapset == NULL || *gmapset == 0)
187  gmapset = G_mapset();
188 
190  if (*subgroup == 0)
191  fd = I_fopen_group_ref_old2(group, gmapset);
192  else
193  fd = I_fopen_subgroup_ref_old2(group, subgroup, gmapset);
195  if (!fd)
196  return 0;
197 
198  while (G_getl2(buf, sizeof buf, fd)) {
199  int n = sscanf(buf, "%255s %255s %15s", name, mapset,
200  color); /* better use INAME_LEN */
201  if (n == 2 || n == 3) {
202  I_add_file_to_group_ref(name, mapset, ref);
203  if (n == 3)
204  set_color(name, mapset, color, ref);
205  }
206  }
207  /* make sure we have a color assignment */
209 
210  fclose(fd);
211  return 1;
212 }
213 
214 static int set_color(const char *name, const char *mapset, const char *color,
215  struct Ref *ref)
216 {
217  int n;
218 
219  for (n = 0; n < ref->nfiles; n++) {
220  if (strcmp(ref->file[n].name, name) == 0 &&
221  strcmp(ref->file[n].mapset, mapset) == 0)
222  break;
223  }
224 
225  if (n < ref->nfiles)
226  while (*color) {
227  switch (*color) {
228  case 'r':
229  case 'R':
230  if (ref->red.n < 0)
231  ref->red.n = n;
232  break;
233  case 'g':
234  case 'G':
235  if (ref->grn.n < 0)
236  ref->grn.n = n;
237  break;
238  case 'b':
239  case 'B':
240  if (ref->blu.n < 0)
241  ref->blu.n = n;
242  break;
243  }
244  color++;
245  }
246 
247  return 0;
248 }
249 
250 int I_init_ref_color_nums(struct Ref *ref)
251 {
252  ref->red.table = NULL;
253  ref->grn.table = NULL;
254  ref->blu.table = NULL;
255 
256  ref->red.index = NULL;
257  ref->grn.index = NULL;
258  ref->blu.index = NULL;
259 
260  if (ref->nfiles <= 0 || ref->red.n >= 0 || ref->blu.n >= 0 ||
261  ref->grn.n >= 0)
262  return 1;
263  switch (ref->nfiles) {
264  case 1:
265  ref->red.n = 0;
266  ref->grn.n = 0;
267  ref->blu.n = 0;
268  break;
269  case 2:
270  ref->blu.n = 0;
271  ref->grn.n = 1;
272  break;
273  case 3:
274  ref->blu.n = 0;
275  ref->grn.n = 1;
276  ref->red.n = 2;
277  break;
278  case 4:
279  ref->blu.n = 0;
280  ref->grn.n = 1;
281  ref->red.n = 3;
282  break;
283  default:
284  ref->blu.n = 1;
285  ref->grn.n = 2;
286  ref->red.n = 4;
287  break;
288  }
289 
290  return 0;
291 }
292 
293 /*!
294  * \brief write group REF file
295  *
296  * Writes the contents of the <b>ref</b> structure to the REF file for
297  * the specified <b>group.</b>
298  * Returns 1 if successful; 0 otherwise (and prints a diagnostic error).
299  * <b>Note.</b> This routine will create the <b>group</b>, if it does not
300  * already exist.
301  *
302  * \param group
303  * \param ref
304  * \return int
305  */
306 int I_put_group_ref(const char *group, const struct Ref *ref)
307 {
308  return put_ref(group, "", ref);
309 }
310 
311 /*!
312  * \brief write subgroup REF file
313  *
314  * Writes the contents of the <b>ref</b>
315  * structure into the REF file for the specified <b>subgroup</b> of the
316  * specified <b>group.</b>
317  * Returns 1 if successful; 0 otherwise (and prints a diagnostic error).
318  * <b>Note.</b> This routine will create the <b>subgroup</b>, if it does not
319  * already exist.
320  *
321  * \param group
322  * \param subgroup
323  * \param ref
324  * \return int
325  */
326 int I_put_subgroup_ref(const char *group, const char *subgroup,
327  const struct Ref *ref)
328 {
329  return put_ref(group, subgroup, ref);
330 }
331 
332 static int put_ref(const char *group, const char *subgroup,
333  const struct Ref *ref)
334 {
335  int n;
336  FILE *fd;
337 
338  if (*subgroup == 0)
339  fd = I_fopen_group_ref_new(group);
340  else
341  fd = I_fopen_subgroup_ref_new(group, subgroup);
342  if (!fd)
343  return 0;
344 
345  for (n = 0; n < ref->nfiles; n++) {
346  fprintf(fd, "%s %s", ref->file[n].name, ref->file[n].mapset);
347  if (n == ref->red.n || n == ref->grn.n || n == ref->blu.n) {
348  fprintf(fd, " ");
349  if (n == ref->red.n)
350  fprintf(fd, "r");
351  if (n == ref->grn.n)
352  fprintf(fd, "g");
353  if (n == ref->blu.n)
354  fprintf(fd, "b");
355  }
356  fprintf(fd, "\n");
357  }
358  fclose(fd);
359  return 1;
360 }
361 
362 /*!
363  * \brief add file name to Ref structure
364  *
365  * This routine adds the file
366  * <b>name</b> and <b>mapset</b> to the list contained in the <b>ref</b>
367  * structure, if it is not already in the list. The <b>ref</b> structure must
368  * have been properly initialized. This routine is used by programs, such as
369  * <i>i.maxlik</i>, to add to the group new raster maps created from files
370  * already in the group.
371  * Returns the index into the <i>file</i> array within the <b>ref</b>
372  * structure for the file after insertion; see
373  * Imagery_Library_Data_Structures.
374  *
375  * \param name
376  * \param mapset
377  * \param ref
378  * \return int
379  */
380 int I_add_file_to_group_ref(const char *name, const char *mapset,
381  struct Ref *ref)
382 {
383  int n;
384 
385  for (n = 0; n < ref->nfiles; n++) {
386  if (strcmp(ref->file[n].name, name) == 0 &&
387  strcmp(ref->file[n].mapset, mapset) == 0)
388  return n;
389  }
390 
391  if ((n = ref->nfiles++))
392  ref->file = (struct Ref_Files *)G_realloc(
393  ref->file, ref->nfiles * sizeof(struct Ref_Files));
394  else
395  ref->file = (struct Ref_Files *)G_malloc(ref->nfiles *
396  sizeof(struct Ref_Files));
397  strcpy(ref->file[n].name, name);
398  strcpy(ref->file[n].mapset, mapset);
399  return n;
400 }
401 
402 /*!
403  * \brief copy Ref lists
404  *
405  * This routine is used to copy file names from one
406  * <i>Ref</i> structure to another. The name and mapset for file <b>n</b>
407  * from the <b>src</b> structure are copied into the <b>dst</b> structure
408  * (which must be properly initialized).
409  * For example, the following code copies one <i>Ref</i> structure to another:
410  \code
411  struct Ref src,dst;
412  int n;
413  // some code to get information into <b>src</b>
414  ...
415  I_init_group_ref (&dst);
416  for (n = 0; n < src.nfiles; n++)
417  I_transfer_group_ref_file (&src, n, &dst);
418  \endcode
419  * This routine is used by <i>g.gui.gcp</i> to create the REF file for a
420  * subgroup.
421  *
422  * \param ref2 Source
423  * \param n
424  * \param ref1 Destination
425  * \return int 0
426  */
427 int I_transfer_group_ref_file(const struct Ref *ref2, int n, struct Ref *ref1)
428 {
429  int k;
430 
431  /* insert old name into new ref */
432  k = I_add_file_to_group_ref(ref2->file[n].name, ref2->file[n].mapset, ref1);
433 
434  /* preserve color assignment */
435  if (n == ref2->red.n)
436  ref1->red.n = k;
437  if (n == ref2->grn.n)
438  ref1->grn.n = k;
439  if (n == ref2->blu.n)
440  ref1->blu.n = k;
441 
442  return 0;
443 }
444 
445 /*!
446  * \brief initialize Ref
447  * structure
448  *
449  * This routine initializes the <b>ref</b> structure for other
450  * library calls which require a <i>Ref</i> structure. This routine must be
451  * called before any use of the structure can be made.
452  * <b>Note.</b> The routines I_get_group_ref and I_get_subgroup_ref call
453  * this routine automatically.
454  *
455  * \param ref
456  * \return int
457  */
458 int I_init_group_ref(struct Ref *ref)
459 {
460  ref->nfiles = 0;
461  ref->red.n = ref->grn.n = ref->blu.n = -1;
462  ref->red.table = ref->grn.table = ref->blu.table = NULL;
463 
464  return 0;
465 }
466 
467 /*!
468  * \brief free Ref structure
469  *
470  * This routine frees memory allocated to the <b>ref</b> structure.
471  *
472  * \param ref
473  * \return int
474  */
475 int I_free_group_ref(struct Ref *ref)
476 {
477  if (ref->nfiles > 0)
478  free(ref->file);
479  ref->nfiles = 0;
480 
481  return 0;
482 }
#define NULL
Definition: ccmath.h:32
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:248
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition: getl.c:60
#define G_realloc(p, n)
Definition: defs/gis.h:96
int G_unqualified_name(const char *, const char *, char *, char *)
Returns unqualified map name (without @ mapset)
Definition: nme_in_mps.c:134
#define G_malloc(n)
Definition: defs/gis.h:94
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition: gis/open.c:216
void int G_suppress_warnings(int)
Suppress printing a warning message to stderr.
Definition: gis/error.c:222
FILE * I_fopen_subgroup_ref_old2(const char *, const char *, const char *)
Definition: ref.c:62
FILE * I_fopen_group_file_new(const char *, const char *)
Definition: fopen.c:69
FILE * I_fopen_subgroup_ref_new(const char *, const char *)
Definition: ref.c:49
FILE * I_fopen_group_file_old(const char *, const char *)
Open group file for reading.
Definition: fopen.c:102
FILE * I_fopen_group_ref_new(const char *)
Definition: ref.c:25
int I_find_group(const char *)
does group exist?
Definition: imagery/find.c:20
FILE * I_fopen_group_ref_old2(const char *, const char *)
Definition: ref.c:35
#define GMAPSET_MAX
Definition: gis.h:197
#define GNAME_MAX
Definition: gis.h:196
int I_get_subgroup(const char *group, char *subgroup)
Definition: group.c:67
int I_put_subgroup_ref(const char *group, const char *subgroup, const struct Ref *ref)
write subgroup REF file
Definition: group.c:326
int I_add_file_to_group_ref(const char *name, const char *mapset, struct Ref *ref)
add file name to Ref structure
Definition: group.c:380
int I_put_subgroup(const char *group, const char *subgroup)
Definition: group.c:86
int I_get_subgroup_ref2(const char *group, const char *subgroup, const char *mapset, struct Ref *ref)
read subgroup REF file
Definition: group.c:165
int I_get_group_ref(const char *group, struct Ref *ref)
read group REF file
Definition: group.c:111
int I_transfer_group_ref_file(const struct Ref *ref2, int n, struct Ref *ref1)
copy Ref lists
Definition: group.c:427
int I_init_ref_color_nums(struct Ref *ref)
Definition: group.c:250
int I_free_group_ref(struct Ref *ref)
free Ref structure
Definition: group.c:475
int I_get_subgroup_ref(const char *group, const char *subgroup, struct Ref *ref)
read subgroup REF file
Definition: group.c:146
int I_get_group_ref2(const char *group, const char *mapset, struct Ref *ref)
read group REF file
Definition: group.c:128
int I_put_group_ref(const char *group, const struct Ref *ref)
write group REF file
Definition: group.c:306
int I_init_group_ref(struct Ref *ref)
initialize Ref structure
Definition: group.c:458
int I_get_group(char *group)
Definition: group.c:37
int I_put_group(const char *group)
Definition: group.c:54
#define INAME_LEN
Definition: imagery.h:8
#define GROUPFILE
Definition: imagery.h:203
#define SUBGROUPFILE
Definition: imagery.h:204
const char * name
Definition: named_colr.c:6
#define strcpy
Definition: parson.c:62
void free(void *)
unsigned char * index
Definition: imagery.h:12
unsigned char * table
Definition: imagery.h:11
int n
Definition: imagery.h:16
char name[256]
Definition: imagery.h:20
char mapset[256]
Definition: imagery.h:21
Definition: imagery.h:24
struct Ref_Color red grn blu
Definition: imagery.h:27
int nfiles
Definition: imagery.h:25
struct Ref_Files * file
Definition: imagery.h:26