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