GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
symbol/read.c
Go to the documentation of this file.
1 
2 /****************************************************************************
3 *
4 * MODULE: Symbol library
5 *
6 * AUTHOR(S): Radim Blazek
7 *
8 * PURPOSE: Read symbol from a file to internal structure
9 *
10 * COPYRIGHT: (C) 2001 by the GRASS Development Team
11 *
12 * This program is free software under the GNU General Public
13 * License (>=v2). Read the file COPYING that comes with GRASS
14 * for details.
15 *
16 *****************************************************************************/
17 #include <stdlib.h>
18 #include <string.h>
19 #include <dirent.h>
20 #include <grass/gis.h>
21 #include <grass/symbol.h>
22 #include <grass/glocale.h>
23 
24 static char key[100], data[500];
25 
26 /* Define currently processed part */
27 #define OBJ_NONE 0
28 #define OBJ_STRING 1
29 #define OBJ_POLYGON 2
30 #define OBJ_RING 3
31 
32 /* stores input to key an data */
33 void get_key_data(char *buf)
34 {
35  char *p;
36 
37  G_debug(3, " get_key_data(): %s", buf);
38 
39  data[0] = '\0';
40 
41  strcpy(key, buf);
42  p = strchr(key, ' ');
43  if (p == NULL)
44  return;
45 
46  p[0] = '\0';
47 
48  p++;
49  if (strlen(p) > 0) {
50  strcpy(data, p);
51  G_chop(data);
52  }
53  G_debug(3, " key = %s data = %s", key, data);
54 }
55 
56 /* --- SYMBOL --- */
57 /* create new empty symbol */
58 SYMBOL *new_symbol(void)
59 {
60  SYMBOL *p;
61 
62  p = (SYMBOL *) G_malloc(sizeof(SYMBOL));
63  p->scale = 1.0;
64  p->count = 0;
65  p->alloc = 0;
66  p->part = NULL;
67  return p;
68 }
69 
70 /* add part to symbol */
71 void add_part(SYMBOL * s, SYMBPART * p)
72 {
73  if (s->count == s->alloc) {
74  s->alloc += 10;
75  s->part =
76  (SYMBPART **) G_realloc(s->part, s->alloc * sizeof(SYMBPART *));
77  }
78  s->part[s->count] = p;
79  s->count++;
80 }
81 
82 /* --- PART --- */
83 /* create new empty part */
84 SYMBPART *new_part(int type)
85 {
86  SYMBPART *p;
87 
88  p = (SYMBPART *) G_malloc(sizeof(SYMBPART));
89  p->type = type;
90  p->count = 0;
91  p->alloc = 0;
92  p->chain = NULL;
93  p->color.color = S_COL_DEFAULT;
94  p->fcolor.color = S_COL_DEFAULT;
95  return p;
96 }
97 
98 /* add chain to part */
99 void add_chain(SYMBPART * p, SYMBCHAIN * s)
100 {
101  if (p->count == p->alloc) {
102  p->alloc += 10;
103  p->chain =
104  (SYMBCHAIN **) G_realloc(p->chain,
105  p->alloc * sizeof(SYMBCHAIN *));
106  }
107  p->chain[p->count] = s;
108  p->count++;
109 }
110 
111 
112 /* --- CHAIN --- */
113 /* create new empty chain */
114 SYMBCHAIN *new_chain(void)
115 {
116  SYMBCHAIN *p;
117 
118  p = (SYMBCHAIN *) G_malloc(sizeof(SYMBCHAIN));
119  p->count = 0;
120  p->alloc = 0;
121  p->elem = NULL;
122  p->scount = 0;
123  p->salloc = 0;
124  p->sx = NULL;
125  p->sy = NULL;
126  return p;
127 }
128 
129 /* add element to chain */
130 void add_element(SYMBCHAIN * s, SYMBEL * e)
131 {
132  if (s->count == s->alloc) {
133  s->alloc += 10;
134  s->elem = (SYMBEL **) G_realloc(s->elem, s->alloc * sizeof(SYMBEL *));
135  }
136  s->elem[s->count] = e;
137  s->count++;
138 }
139 
140 /* --- ELEMENT --- */
141 /* create new empty line */
142 SYMBEL *new_line(void)
143 {
144  SYMBEL *p;
145 
146  p = (SYMBEL *) G_malloc(sizeof(SYMBEL));
147  p->type = S_LINE;
148  p->coor.line.count = 0;
149  p->coor.line.alloc = 0;
150  p->coor.line.x = NULL;
151  p->coor.line.y = NULL;
152  return p;
153 }
154 
155 /* add point to line */
156 void add_point(SYMBEL * el, double x, double y)
157 {
158  if (el->coor.line.count == el->coor.line.alloc) {
159  el->coor.line.alloc += 10;
160  el->coor.line.x =
161  (double *)G_realloc(el->coor.line.x,
162  el->coor.line.alloc * sizeof(double));
163  el->coor.line.y =
164  (double *)G_realloc(el->coor.line.y,
165  el->coor.line.alloc * sizeof(double));
166  }
167  el->coor.line.x[el->coor.line.count] = x;
168  el->coor.line.y[el->coor.line.count] = y;
169  el->coor.line.count++;
170 }
171 
172 /* create new arc */
173 SYMBEL *new_arc(double x, double y, double r, double a1, double a2, int c)
174 {
175  SYMBEL *p;
176 
177  p = (SYMBEL *) G_malloc(sizeof(SYMBEL));
178  p->type = S_ARC;
179  p->coor.arc.clock = c;
180  p->coor.arc.x = x;
181  p->coor.arc.y = y;
182  p->coor.arc.r = r;
183  p->coor.arc.a1 = a1;
184  p->coor.arc.a2 = a2;
185  return p;
186 }
187 
188 /* read line coordinates */
189 void read_coor(FILE * fp, SYMBEL * e)
190 {
191  char buf[501];
192  double x, y;
193 
194  G_debug(5, " read_coor()");
195 
196  while (G_getl2(buf, 500, fp) != 0) {
197  G_chop(buf);
198 
199  /* skip empty and comment lines */
200  if ((buf[0] == '#') || (buf[0] == '\0'))
201  continue;
202 
203  get_key_data(buf);
204 
205  if (strcmp(key, "END") == 0) {
206  G_debug(5, " LINE END");
207  return;
208  }
209 
210  if (sscanf(buf, "%lf %lf", &x, &y) != 2) {
211  G_warning(_("Cannot read symbol line coordinates: %s"), buf);
212  return;
213  }
214  G_debug(5, " x = %f y = %f", x, y);
215  add_point(e, x, y);
216  }
217 }
218 
219 /* close file free symbol, print message, return NULL */
220 SYMBOL *err(FILE * fp, SYMBOL * s, char *msg)
221 {
222  fclose(fp);
223  G_free(s); /* TODO: free all */
224  G_warning(msg);
225  return NULL;
226 }
227 
228 /*
229  * Read symbol specified by name.
230  * Name: group/name | group/name@mapset
231  * (later add syntax to prefer symbol from GISBASE)
232  * S_read() searches first in mapsets (standard GRASS search) and
233  * then in GISBASE/etc/symbol/
234  */
235 SYMBOL *S_read(char *sname)
236 {
237  int i, j, k, l;
238  FILE *fp;
239  char group[500], name[500], buf[2001];
240  char *ms, *c;
241  double x, y, x2, y2, rad, ang1, ang2;
242  int r, g, b;
243  double fr, fg, fb;
244  int ret;
245  char clock;
246  SYMBOL *symb;
247  int current; /* current part_type */
248  SYMBPART *part; /* current part */
249  SYMBCHAIN *chain; /* current chain */
250  SYMBEL *elem; /* current element */
251 
252  G_debug(3, "S_read(): sname = %s", sname);
253 
254  /* Find file */
255  /* Get group and name */
256  strcpy(group, sname);
257  c = strchr(group, '/');
258  if (c == NULL) {
259  G_warning(_("Incorrect symbol name: '%s' (should be: group/name or group/name@mapset)"),
260  sname);
261  return NULL;
262  }
263  c[0] = '\0';
264 
265  c++;
266  strcpy(name, c);
267 
268  G_debug(3, " group: '%s' name: '%s'", group, name);
269 
270  /* Search in mapsets */
271  sprintf(buf, "symbol/%s", group);
272  ms = G_find_file(buf, name, NULL);
273 
274  if (ms != NULL) { /* Found in mapsets */
275  fp = G_fopen_old(buf, name, ms);
276  }
277  else { /* Search in GISBASE */
278  sprintf(buf, "%s/etc/symbol/%s", G_gisbase(), sname);
279  fp = fopen(buf, "r");
280  }
281 
282  if (fp == NULL) {
283  G_warning(_("Cannot find/open symbol: '%s'"), sname);
284  return NULL;
285  }
286 
287  /* create new symbol */
288  symb = new_symbol();
289 
290  current = OBJ_NONE; /* no part */
291 
292  /* read file */
293  while (G_getl2(buf, 2000, fp) != 0) {
294  G_chop(buf);
295  G_debug(3, " BUF: [%s]", buf);
296 
297  /* skip empty and comment lines */
298  if ((buf[0] == '#') || (buf[0] == '\0'))
299  continue;
300 
301  get_key_data(buf);
302 
303  if (strcmp(key, "VERSION") == 0) {
304  if (strcmp(data, "1.0") != 0) {
305  sprintf(buf, "Wrong symbol version: '%s'", data);
306  return (err(fp, symb, buf));
307  }
308  }
309  else if (strcmp(key, "BOX") == 0) {
310  if (sscanf(data, "%lf %lf %lf %lf", &x, &y, &x2, &y2) != 4) {
311  sprintf(buf, "Incorrect box definition: '%s'", data);
312  return (err(fp, symb, buf));
313  }
314  if (x2 - x > y2 - y)
315  symb->scale = 1 / (x2 - x);
316  else
317  symb->scale = 1 / (y2 - y);
318  }
319  else if (strcmp(key, "STRING") == 0) {
320  G_debug(4, " STRING >");
321  current = OBJ_STRING;
322  part = new_part(S_STRING);
323  add_part(symb, part);
324 
325  chain = new_chain();
326  add_chain(part, chain);
327  }
328  else if (strcmp(key, "POLYGON") == 0) {
329  G_debug(4, " POLYGON >");
330  current = OBJ_POLYGON;
331  part = new_part(S_POLYGON);
332  add_part(symb, part);
333 
334  }
335  else if (strcmp(key, "RING") == 0) {
336  G_debug(4, " RING >");
337  current = OBJ_RING;
338  chain = new_chain();
339  add_chain(part, chain);
340 
341  }
342  else if (strcmp(key, "LINE") == 0) {
343  G_debug(4, " LINE >");
344  elem = new_line();
345  add_element(chain, elem);
346  read_coor(fp, elem);
347 
348  }
349  else if (strcmp(key, "ARC") == 0) {
350  G_debug(4, " ARC");
351  ret =
352  sscanf(data, "%lf %lf %lf %lf %lf %c", &x, &y, &rad, &ang1,
353  &ang2, &clock);
354  if (ret < 5) {
355  sprintf(buf, "Incorrect arc definition: '%s'", buf);
356  return (err(fp, symb, buf));
357  }
358  if (ret == 6 && (clock == 'c' || clock == 'C'))
359  i = 1;
360  else
361  i = 0;
362  elem = new_arc(x, y, rad, ang1, ang2, i);
363  add_element(chain, elem);
364 
365  }
366  else if (strcmp(key, "END") == 0) {
367  switch (current) {
368  case OBJ_STRING:
369  G_debug(4, " STRING END");
370  current = OBJ_NONE;
371  break;
372  case OBJ_POLYGON:
373  G_debug(4, " POLYGON END");
374  current = OBJ_NONE;
375  break;
376  case OBJ_RING:
377  G_debug(4, " RING END");
378  current = OBJ_POLYGON;
379  break;
380  }
381  }
382  else if (strcmp(key, "COLOR") == 0) {
383  if (G_strcasecmp(data, "NONE") == 0) {
384  part->color.color = S_COL_NONE;
385  }
386  else if (sscanf(data, "%d %d %d", &r, &g, &b) == 3) {
387  if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255)
388  G_warning(_("Incorrect symbol color: '%s', using default."),
389  buf);
390  else {
391  fr = r / 255.0;
392  fg = g / 255.0;
393  fb = b / 255.0;
394  part->color.color = S_COL_DEFINED;
395  part->color.r = r;
396  part->color.g = g;
397  part->color.b = b;
398  part->color.fr = fr;
399  part->color.fg = fg;
400  part->color.fb = fb;
401  G_debug(4, " color [%d %d %d] = [%.3f %.3f %.3f]", r, g,
402  b, fr, fg, fb);
403  }
404  }
405  else {
406  G_warning(_("Incorrect symbol color: '%s', using default."),
407  buf);
408  }
409  }
410  else if (strcmp(key, "FCOLOR") == 0) {
411  if (G_strcasecmp(data, "NONE") == 0) {
412  part->fcolor.color = S_COL_NONE;
413  }
414  else if (sscanf(data, "%d %d %d", &r, &g, &b) == 3) {
415  if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255)
416  G_warning(_("Incorrect symbol color: '%s', using default."),
417  buf);
418  else {
419  fr = r / 255.0;
420  fg = g / 255.0;
421  fb = b / 255.0;
422  part->fcolor.color = S_COL_DEFINED;
423  part->fcolor.r = r;
424  part->fcolor.g = g;
425  part->fcolor.b = b;
426  part->fcolor.fr = fr;
427  part->fcolor.fg = fg;
428  part->fcolor.fb = fb;
429  G_debug(4, " color [%d %d %d] = [%.3f %.3f %.3f]", r, g,
430  b, fr, fg, fb);
431  }
432  }
433  else {
434  G_warning(_("Incorrect symbol color: '%s', using default."),
435  buf);
436  }
437  }
438  else {
439  sprintf(buf, "Unknown keyword in symbol: '%s'", buf);
440  return (err(fp, symb, buf));
441  break;
442  }
443  }
444 
445  /* Debug output */
446 
447  G_debug(3, "Number of parts: %d", symb->count);
448  for (i = 0; i < symb->count; i++) {
449  part = symb->part[i];
450  G_debug(4, " Part %d: type: %d number of chains: %d", i, part->type,
451  part->count);
452  G_debug(4, " color: %d: fcolor: %d", part->color.color,
453  part->fcolor.color);
454  for (j = 0; j < part->count; j++) {
455  chain = part->chain[j];
456  G_debug(4, " Chain %d: number of elements: %d", j,
457  chain->count);
458  for (k = 0; k < chain->count; k++) {
459  elem = chain->elem[k];
460  G_debug(4, " Element %d: type: %d", k, elem->type);
461  if (elem->type == S_LINE) {
462  G_debug(4, " Number of points %d",
463  elem->coor.line.count);
464  for (l = 0; l < elem->coor.line.count; l++) {
465  G_debug(4, " x, y: %f %f",
466  elem->coor.line.x[l], elem->coor.line.y[l]);
467  }
468  }
469  else {
470  G_debug(4, " arc r = %f", elem->coor.arc.r);
471  }
472  }
473  }
474  }
475 
476  fclose(fp);
477 
478  return symb;
479 }
#define OBJ_POLYGON
Definition: symbol/read.c:29
int G_strcasecmp(const char *x, const char *y)
String compare ignoring case (upper or lower)
Definition: strings.c:192
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
int l
Definition: dataquad.c:292
float b
Definition: named_colr.c:8
void read_coor(FILE *fp, SYMBEL *e)
Definition: symbol/read.c:189
string name
Definition: render.py:1314
SYMBCHAIN * new_chain(void)
Definition: symbol/read.c:114
void get_key_data(char *buf)
Definition: symbol/read.c:33
float r
Definition: named_colr.c:8
SYMBOL * new_symbol(void)
Definition: symbol/read.c:58
const char * err
Definition: g3dcolor.c:50
SYMBEL * new_arc(double x, double y, double r, double a1, double a2, int c)
Definition: symbol/read.c:173
#define OBJ_STRING
Definition: symbol/read.c:28
char * G_chop(char *line)
Chop leading and trailing white spaces:
Definition: strings.c:418
int y
Definition: plot.c:34
void add_element(SYMBCHAIN *s, SYMBEL *e)
Definition: symbol/read.c:130
#define OBJ_NONE
Definition: symbol/read.c:27
int G_getl2(char *buf, int n, FILE *fd)
gets a line of text from a file of any pedigree
Definition: getl.c:52
tuple data
void add_chain(SYMBPART *p, SYMBCHAIN *s)
Definition: symbol/read.c:99
SYMBOL * S_read(char *sname)
Definition: symbol/read.c:235
float g
Definition: named_colr.c:8
SYMBEL * new_line(void)
Definition: symbol/read.c:142
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
Definition: g3drange.c:62
return NULL
Definition: dbfopen.c:1394
tuple msg
Definition: wxnviz.py:32
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
fclose(fd)
SYMBPART * new_part(int type)
Definition: symbol/read.c:84
char * G_gisbase(void)
top level module directory
Definition: gisbase.c:42
#define OBJ_RING
Definition: symbol/read.c:30
char * G_find_file(const char *element, char *name, const char *mapset)
searches for a file from the mapset search list or in a specified mapset. returns the mapset name whe...
Definition: find_file.c:159
FILE * G_fopen_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition: gis/open.c:226
void add_part(SYMBOL *s, SYMBPART *p)
Definition: symbol/read.c:71
void add_point(SYMBEL *el, double x, double y)
Definition: symbol/read.c:156