read.c 11 KB

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