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