GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-f622271e7a
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 
112 int I_get_group_ref(const char *group, struct Ref *ref)
113 {
114  return get_ref(group, "", NULL, ref);
115 }
116 
117 /*!
118  * \brief read group REF file
119  *
120  * Reads the contents of the REF file for the specified <b>group</b> into
121  * the <b>ref</b> structure.
122  * Returns 1 if successful; 0 otherwise (but no error messages are printed).
123  *
124  * \param group
125  * \param mapset
126  * \param ref
127  * \return int
128  */
129 
130 int I_get_group_ref2(const char *group, const char *mapset, struct Ref *ref)
131 {
132  return get_ref(group, "", mapset, ref);
133 }
134 
135 /*!
136  * \brief read subgroup REF file
137  *
138  * Reads the contents of the REF file for the
139  * specified <b>subgroup</b> of the specified <b>group</b> into the
140  * <b>ref</b> structure.
141  * Returns 1 if successful; 0 otherwise (but no error messages are printed).
142  *
143  * \param group
144  * \param subgroup
145  * \param ref
146  * \return int
147  */
148 
149 int I_get_subgroup_ref(const char *group, const char *subgroup, struct Ref *ref)
150 {
151  return get_ref(group, subgroup, NULL, ref);
152 }
153 
154 /*!
155  * \brief read subgroup REF file
156  *
157  * Reads the contents of the REF file for the
158  * specified <b>subgroup</b> of the specified <b>group</b> into the
159  * <b>ref</b> structure.
160  * Returns 1 if successful; 0 otherwise (but no error messages are printed).
161  *
162  * \param group
163  * \param subgroup
164  * \param mapset
165  * \param ref
166  * \return int
167  */
168 int I_get_subgroup_ref2(const char *group, const char *subgroup,
169  const char *mapset, struct Ref *ref)
170 {
171  return get_ref(group, subgroup, mapset, ref);
172 }
173 
174 static int get_ref(const char *group, const char *subgroup, const char *gmapset,
175  struct Ref *ref)
176 {
177  char buf[1024];
178  char name[INAME_LEN], mapset[INAME_LEN];
179  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
180  char color[20];
181  FILE *fd;
182 
183  I_init_group_ref(ref);
184 
185  G_unqualified_name(group, gmapset, xname, xmapset);
186  group = xname;
187  gmapset = xmapset;
188 
189  if (gmapset == NULL || *gmapset == 0)
190  gmapset = G_mapset();
191 
193  if (*subgroup == 0)
194  fd = I_fopen_group_ref_old2(group, gmapset);
195  else
196  fd = I_fopen_subgroup_ref_old2(group, subgroup, gmapset);
198  if (!fd)
199  return 0;
200 
201  while (G_getl2(buf, sizeof buf, fd)) {
202  int n = sscanf(buf, "%255s %255s %15s", name, mapset,
203  color); /* better use INAME_LEN */
204  if (n == 2 || n == 3) {
205  I_add_file_to_group_ref(name, mapset, ref);
206  if (n == 3)
207  set_color(name, mapset, color, ref);
208  }
209  }
210  /* make sure we have a color assignment */
212 
213  fclose(fd);
214  return 1;
215 }
216 
217 static int set_color(const char *name, const char *mapset, const char *color,
218  struct Ref *ref)
219 {
220  int n;
221 
222  for (n = 0; n < ref->nfiles; n++) {
223  if (strcmp(ref->file[n].name, name) == 0 &&
224  strcmp(ref->file[n].mapset, mapset) == 0)
225  break;
226  }
227 
228  if (n < ref->nfiles)
229  while (*color) {
230  switch (*color) {
231  case 'r':
232  case 'R':
233  if (ref->red.n < 0)
234  ref->red.n = n;
235  break;
236  case 'g':
237  case 'G':
238  if (ref->grn.n < 0)
239  ref->grn.n = n;
240  break;
241  case 'b':
242  case 'B':
243  if (ref->blu.n < 0)
244  ref->blu.n = n;
245  break;
246  }
247  color++;
248  }
249 
250  return 0;
251 }
252 
253 int I_init_ref_color_nums(struct Ref *ref)
254 {
255  ref->red.table = NULL;
256  ref->grn.table = NULL;
257  ref->blu.table = NULL;
258 
259  ref->red.index = NULL;
260  ref->grn.index = NULL;
261  ref->blu.index = NULL;
262 
263  if (ref->nfiles <= 0 || ref->red.n >= 0 || ref->blu.n >= 0 ||
264  ref->grn.n >= 0)
265  return 1;
266  switch (ref->nfiles) {
267  case 1:
268  ref->red.n = 0;
269  ref->grn.n = 0;
270  ref->blu.n = 0;
271  break;
272  case 2:
273  ref->blu.n = 0;
274  ref->grn.n = 1;
275  break;
276  case 3:
277  ref->blu.n = 0;
278  ref->grn.n = 1;
279  ref->red.n = 2;
280  break;
281  case 4:
282  ref->blu.n = 0;
283  ref->grn.n = 1;
284  ref->red.n = 3;
285  break;
286  default:
287  ref->blu.n = 1;
288  ref->grn.n = 2;
289  ref->red.n = 4;
290  break;
291  }
292 
293  return 0;
294 }
295 
296 /*!
297  * \brief write group REF file
298  *
299  * Writes the contents of the <b>ref</b> structure to the REF file for
300  * the specified <b>group.</b>
301  * Returns 1 if successful; 0 otherwise (and prints a diagnostic error).
302  * <b>Note.</b> This routine will create the <b>group</b>, if it does not
303  * already exist.
304  *
305  * \param group
306  * \param ref
307  * \return int
308  */
309 
310 int I_put_group_ref(const char *group, const struct Ref *ref)
311 {
312  return put_ref(group, "", ref);
313 }
314 
315 /*!
316  * \brief write subgroup REF file
317  *
318  * Writes the contents of the <b>ref</b>
319  * structure into the REF file for the specified <b>subgroup</b> of the
320  * specified <b>group.</b>
321  * Returns 1 if successful; 0 otherwise (and prints a diagnostic error).
322  * <b>Note.</b> This routine will create the <b>subgroup</b>, if it does not
323  * already exist.
324  *
325  * \param group
326  * \param subgroup
327  * \param ref
328  * \return int
329  */
330 
331 int I_put_subgroup_ref(const char *group, const char *subgroup,
332  const struct Ref *ref)
333 {
334  return put_ref(group, subgroup, ref);
335 }
336 
337 static int put_ref(const char *group, const char *subgroup,
338  const struct Ref *ref)
339 {
340  int n;
341  FILE *fd;
342 
343  if (*subgroup == 0)
344  fd = I_fopen_group_ref_new(group);
345  else
346  fd = I_fopen_subgroup_ref_new(group, subgroup);
347  if (!fd)
348  return 0;
349 
350  for (n = 0; n < ref->nfiles; n++) {
351  fprintf(fd, "%s %s", ref->file[n].name, ref->file[n].mapset);
352  if (n == ref->red.n || n == ref->grn.n || n == ref->blu.n) {
353  fprintf(fd, " ");
354  if (n == ref->red.n)
355  fprintf(fd, "r");
356  if (n == ref->grn.n)
357  fprintf(fd, "g");
358  if (n == ref->blu.n)
359  fprintf(fd, "b");
360  }
361  fprintf(fd, "\n");
362  }
363  fclose(fd);
364  return 1;
365 }
366 
367 /*!
368  * \brief add file name to Ref structure
369  *
370  * This routine adds the file
371  * <b>name</b> and <b>mapset</b> to the list contained in the <b>ref</b>
372  * structure, if it is not already in the list. The <b>ref</b> structure must
373  * have been properly initialized. This routine is used by programs, such as
374  * <i>i.maxlik</i>, to add to the group new raster maps created from files
375  * already in the group.
376  * Returns the index into the <i>file</i> array within the <b>ref</b>
377  * structure for the file after insertion; see
378  * Imagery_Library_Data_Structures.
379  *
380  * \param name
381  * \param mapset
382  * \param ref
383  * \return int
384  */
385 
386 int I_add_file_to_group_ref(const char *name, const char *mapset,
387  struct Ref *ref)
388 {
389  int n;
390 
391  for (n = 0; n < ref->nfiles; n++) {
392  if (strcmp(ref->file[n].name, name) == 0 &&
393  strcmp(ref->file[n].mapset, mapset) == 0)
394  return n;
395  }
396 
397  if ((n = ref->nfiles++))
398  ref->file = (struct Ref_Files *)G_realloc(
399  ref->file, ref->nfiles * sizeof(struct Ref_Files));
400  else
401  ref->file = (struct Ref_Files *)G_malloc(ref->nfiles *
402  sizeof(struct Ref_Files));
403  strcpy(ref->file[n].name, name);
404  strcpy(ref->file[n].mapset, mapset);
405  return n;
406 }
407 
408 /*!
409  * \brief copy Ref lists
410  *
411  * This routine is used to copy file names from one
412  * <i>Ref</i> structure to another. The name and mapset for file <b>n</b>
413  * from the <b>src</b> structure are copied into the <b>dst</b> structure
414  * (which must be properly initialized).
415  * For example, the following code copies one <i>Ref</i> structure to another:
416  \code
417  struct Ref src,dst;
418  int n;
419  // some code to get information into <b>src</b>
420  ...
421  I_init_group_ref (&dst);
422  for (n = 0; n < src.nfiles; n++)
423  I_transfer_group_ref_file (&src, n, &dst);
424  \endcode
425  * This routine is used by <i>g.gui.gcp</i> to create the REF file for a
426  * subgroup.
427  *
428  * \param src
429  * \param n
430  * \param dst
431  * \return int
432  */
433 
434 int I_transfer_group_ref_file(const struct Ref *ref2, int n, struct Ref *ref1)
435 {
436  int k;
437 
438  /* insert old name into new ref */
439  k = I_add_file_to_group_ref(ref2->file[n].name, ref2->file[n].mapset, ref1);
440 
441  /* preserve color assignment */
442  if (n == ref2->red.n)
443  ref1->red.n = k;
444  if (n == ref2->grn.n)
445  ref1->grn.n = k;
446  if (n == ref2->blu.n)
447  ref1->blu.n = k;
448 
449  return 0;
450 }
451 
452 /*!
453  * \brief initialize Ref
454  * structure
455  *
456  * This routine initializes the <b>ref</b> structure for other
457  * library calls which require a <i>Ref</i> structure. This routine must be
458  * called before any use of the structure can be made.
459  * <b>Note.</b> The routines I_get_group_ref and I_get_subgroup_ref call
460  * this routine automatically.
461  *
462  * \param ref
463  * \return int
464  */
465 
466 int I_init_group_ref(struct Ref *ref)
467 {
468  ref->nfiles = 0;
469  ref->red.n = ref->grn.n = ref->blu.n = -1;
470  ref->red.table = ref->grn.table = ref->blu.table = NULL;
471 
472  return 0;
473 }
474 
475 /*!
476  * \brief free Ref structure
477  *
478  * This routine frees memory allocated to the <b>ref</b> structure.
479  *
480  * \param ref
481  * \return int
482  */
483 
484 int I_free_group_ref(struct Ref *ref)
485 {
486  if (ref->nfiles > 0)
487  free(ref->file);
488  ref->nfiles = 0;
489 
490  return 0;
491 }
#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:251
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:219
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:21
FILE * I_fopen_group_ref_old2(const char *, const char *)
Definition: ref.c:35
#define GMAPSET_MAX
Definition: gis.h:192
#define GNAME_MAX
Definition: gis.h:191
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:331
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:386
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:168
int I_get_group_ref(const char *group, struct Ref *ref)
read group REF file
Definition: group.c:112
int I_transfer_group_ref_file(const struct Ref *ref2, int n, struct Ref *ref1)
copy Ref lists
Definition: group.c:434
int I_init_ref_color_nums(struct Ref *ref)
Definition: group.c:253
int I_free_group_ref(struct Ref *ref)
free Ref structure
Definition: group.c:484
int I_get_subgroup_ref(const char *group, const char *subgroup, struct Ref *ref)
read subgroup REF file
Definition: group.c:149
int I_get_group_ref2(const char *group, const char *mapset, struct Ref *ref)
read group REF file
Definition: group.c:130
int I_put_group_ref(const char *group, const struct Ref *ref)
write group REF file
Definition: group.c:310
int I_init_group_ref(struct Ref *ref)
initialize Ref structure
Definition: group.c:466
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[INAME_LEN]
Definition: imagery.h:20
char mapset[INAME_LEN]
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