GRASS Programmer's Manual
6.4.2(2012)
|
00001 00002 /**************************************************************************** 00003 * 00004 * MODULE: Symbol library 00005 * 00006 * AUTHOR(S): Radim Blazek 00007 * 00008 * PURPOSE: Read symbol from a file to internal structure 00009 * 00010 * COPYRIGHT: (C) 2001 by the GRASS Development Team 00011 * 00012 * This program is free software under the GNU General Public 00013 * License (>=v2). Read the file COPYING that comes with GRASS 00014 * for details. 00015 * 00016 *****************************************************************************/ 00017 #include <stdlib.h> 00018 #include <string.h> 00019 #include <dirent.h> 00020 #include <grass/gis.h> 00021 #include <grass/symbol.h> 00022 #include <grass/glocale.h> 00023 00024 static char key[100], data[500]; 00025 00026 /* Define currently processed part */ 00027 #define OBJ_NONE 0 00028 #define OBJ_STRING 1 00029 #define OBJ_POLYGON 2 00030 #define OBJ_RING 3 00031 00032 /* stores input to key an data */ 00033 void get_key_data(char *buf) 00034 { 00035 char *p; 00036 00037 G_debug(3, " get_key_data(): %s", buf); 00038 00039 data[0] = '\0'; 00040 00041 strcpy(key, buf); 00042 p = strchr(key, ' '); 00043 if (p == NULL) 00044 return; 00045 00046 p[0] = '\0'; 00047 00048 p++; 00049 if (strlen(p) > 0) { 00050 strcpy(data, p); 00051 G_chop(data); 00052 } 00053 G_debug(3, " key = %s data = %s", key, data); 00054 } 00055 00056 /* --- SYMBOL --- */ 00057 /* create new empty symbol */ 00058 SYMBOL *new_symbol(void) 00059 { 00060 SYMBOL *p; 00061 00062 p = (SYMBOL *) G_malloc(sizeof(SYMBOL)); 00063 p->scale = 1.0; 00064 p->count = 0; 00065 p->alloc = 0; 00066 p->part = NULL; 00067 return p; 00068 } 00069 00070 /* add part to symbol */ 00071 void add_part(SYMBOL * s, SYMBPART * p) 00072 { 00073 if (s->count == s->alloc) { 00074 s->alloc += 10; 00075 s->part = 00076 (SYMBPART **) G_realloc(s->part, s->alloc * sizeof(SYMBPART *)); 00077 } 00078 s->part[s->count] = p; 00079 s->count++; 00080 } 00081 00082 /* --- PART --- */ 00083 /* create new empty part */ 00084 SYMBPART *new_part(int type) 00085 { 00086 SYMBPART *p; 00087 00088 p = (SYMBPART *) G_malloc(sizeof(SYMBPART)); 00089 p->type = type; 00090 p->count = 0; 00091 p->alloc = 0; 00092 p->chain = NULL; 00093 p->color.color = S_COL_DEFAULT; 00094 p->fcolor.color = S_COL_DEFAULT; 00095 return p; 00096 } 00097 00098 /* add chain to part */ 00099 void add_chain(SYMBPART * p, SYMBCHAIN * s) 00100 { 00101 if (p->count == p->alloc) { 00102 p->alloc += 10; 00103 p->chain = 00104 (SYMBCHAIN **) G_realloc(p->chain, 00105 p->alloc * sizeof(SYMBCHAIN *)); 00106 } 00107 p->chain[p->count] = s; 00108 p->count++; 00109 } 00110 00111 00112 /* --- CHAIN --- */ 00113 /* create new empty chain */ 00114 SYMBCHAIN *new_chain(void) 00115 { 00116 SYMBCHAIN *p; 00117 00118 p = (SYMBCHAIN *) G_malloc(sizeof(SYMBCHAIN)); 00119 p->count = 0; 00120 p->alloc = 0; 00121 p->elem = NULL; 00122 p->scount = 0; 00123 p->salloc = 0; 00124 p->sx = NULL; 00125 p->sy = NULL; 00126 return p; 00127 } 00128 00129 /* add element to chain */ 00130 void add_element(SYMBCHAIN * s, SYMBEL * e) 00131 { 00132 if (s->count == s->alloc) { 00133 s->alloc += 10; 00134 s->elem = (SYMBEL **) G_realloc(s->elem, s->alloc * sizeof(SYMBEL *)); 00135 } 00136 s->elem[s->count] = e; 00137 s->count++; 00138 } 00139 00140 /* --- ELEMENT --- */ 00141 /* create new empty line */ 00142 SYMBEL *new_line(void) 00143 { 00144 SYMBEL *p; 00145 00146 p = (SYMBEL *) G_malloc(sizeof(SYMBEL)); 00147 p->type = S_LINE; 00148 p->coor.line.count = 0; 00149 p->coor.line.alloc = 0; 00150 p->coor.line.x = NULL; 00151 p->coor.line.y = NULL; 00152 return p; 00153 } 00154 00155 /* add point to line */ 00156 void add_point(SYMBEL * el, double x, double y) 00157 { 00158 if (el->coor.line.count == el->coor.line.alloc) { 00159 el->coor.line.alloc += 10; 00160 el->coor.line.x = 00161 (double *)G_realloc(el->coor.line.x, 00162 el->coor.line.alloc * sizeof(double)); 00163 el->coor.line.y = 00164 (double *)G_realloc(el->coor.line.y, 00165 el->coor.line.alloc * sizeof(double)); 00166 } 00167 el->coor.line.x[el->coor.line.count] = x; 00168 el->coor.line.y[el->coor.line.count] = y; 00169 el->coor.line.count++; 00170 } 00171 00172 /* create new arc */ 00173 SYMBEL *new_arc(double x, double y, double r, double a1, double a2, int c) 00174 { 00175 SYMBEL *p; 00176 00177 p = (SYMBEL *) G_malloc(sizeof(SYMBEL)); 00178 p->type = S_ARC; 00179 p->coor.arc.clock = c; 00180 p->coor.arc.x = x; 00181 p->coor.arc.y = y; 00182 p->coor.arc.r = r; 00183 p->coor.arc.a1 = a1; 00184 p->coor.arc.a2 = a2; 00185 return p; 00186 } 00187 00188 /* read line coordinates */ 00189 void read_coor(FILE * fp, SYMBEL * e) 00190 { 00191 char buf[501]; 00192 double x, y; 00193 00194 G_debug(5, " read_coor()"); 00195 00196 while (G_getl2(buf, 500, fp) != 0) { 00197 G_chop(buf); 00198 00199 /* skip empty and comment lines */ 00200 if ((buf[0] == '#') || (buf[0] == '\0')) 00201 continue; 00202 00203 get_key_data(buf); 00204 00205 if (strcmp(key, "END") == 0) { 00206 G_debug(5, " LINE END"); 00207 return; 00208 } 00209 00210 if (sscanf(buf, "%lf %lf", &x, &y) != 2) { 00211 G_warning(_("Cannot read symbol line coordinates: %s"), buf); 00212 return; 00213 } 00214 G_debug(5, " x = %f y = %f", x, y); 00215 add_point(e, x, y); 00216 } 00217 } 00218 00219 /* close file free symbol, print message, return NULL */ 00220 SYMBOL *err(FILE * fp, SYMBOL * s, char *msg) 00221 { 00222 fclose(fp); 00223 G_free(s); /* TODO: free all */ 00224 G_warning(msg); 00225 return NULL; 00226 } 00227 00228 /* 00229 * Read symbol specified by name. 00230 * Name: group/name | group/name@mapset 00231 * (later add syntax to prefer symbol from GISBASE) 00232 * S_read() searches first in mapsets (standard GRASS search) and 00233 * then in GISBASE/etc/symbol/ 00234 */ 00235 SYMBOL *S_read(char *sname) 00236 { 00237 int i, j, k, l; 00238 FILE *fp; 00239 char group[500], name[500], buf[2001]; 00240 char *ms, *c; 00241 double x, y, x2, y2, rad, ang1, ang2; 00242 int r, g, b; 00243 double fr, fg, fb; 00244 int ret; 00245 char clock; 00246 SYMBOL *symb; 00247 int current; /* current part_type */ 00248 SYMBPART *part; /* current part */ 00249 SYMBCHAIN *chain; /* current chain */ 00250 SYMBEL *elem; /* current element */ 00251 00252 G_debug(3, "S_read(): sname = %s", sname); 00253 00254 /* Find file */ 00255 /* Get group and name */ 00256 strcpy(group, sname); 00257 c = strchr(group, '/'); 00258 if (c == NULL) { 00259 G_warning(_("Incorrect symbol name: '%s' (should be: group/name or group/name@mapset)"), 00260 sname); 00261 return NULL; 00262 } 00263 c[0] = '\0'; 00264 00265 c++; 00266 strcpy(name, c); 00267 00268 G_debug(3, " group: '%s' name: '%s'", group, name); 00269 00270 /* Search in mapsets */ 00271 sprintf(buf, "symbol/%s", group); 00272 ms = G_find_file(buf, name, NULL); 00273 00274 if (ms != NULL) { /* Found in mapsets */ 00275 fp = G_fopen_old(buf, name, ms); 00276 } 00277 else { /* Search in GISBASE */ 00278 sprintf(buf, "%s/etc/symbol/%s", G_gisbase(), sname); 00279 fp = fopen(buf, "r"); 00280 } 00281 00282 if (fp == NULL) { 00283 G_warning(_("Cannot find/open symbol: '%s'"), sname); 00284 return NULL; 00285 } 00286 00287 /* create new symbol */ 00288 symb = new_symbol(); 00289 00290 current = OBJ_NONE; /* no part */ 00291 00292 /* read file */ 00293 while (G_getl2(buf, 2000, fp) != 0) { 00294 G_chop(buf); 00295 G_debug(3, " BUF: [%s]", buf); 00296 00297 /* skip empty and comment lines */ 00298 if ((buf[0] == '#') || (buf[0] == '\0')) 00299 continue; 00300 00301 get_key_data(buf); 00302 00303 if (strcmp(key, "VERSION") == 0) { 00304 if (strcmp(data, "1.0") != 0) { 00305 sprintf(buf, "Wrong symbol version: '%s'", data); 00306 return (err(fp, symb, buf)); 00307 } 00308 } 00309 else if (strcmp(key, "BOX") == 0) { 00310 if (sscanf(data, "%lf %lf %lf %lf", &x, &y, &x2, &y2) != 4) { 00311 sprintf(buf, "Incorrect box definition: '%s'", data); 00312 return (err(fp, symb, buf)); 00313 } 00314 if (x2 - x > y2 - y) 00315 symb->scale = 1 / (x2 - x); 00316 else 00317 symb->scale = 1 / (y2 - y); 00318 } 00319 else if (strcmp(key, "STRING") == 0) { 00320 G_debug(4, " STRING >"); 00321 current = OBJ_STRING; 00322 part = new_part(S_STRING); 00323 add_part(symb, part); 00324 00325 chain = new_chain(); 00326 add_chain(part, chain); 00327 } 00328 else if (strcmp(key, "POLYGON") == 0) { 00329 G_debug(4, " POLYGON >"); 00330 current = OBJ_POLYGON; 00331 part = new_part(S_POLYGON); 00332 add_part(symb, part); 00333 00334 } 00335 else if (strcmp(key, "RING") == 0) { 00336 G_debug(4, " RING >"); 00337 current = OBJ_RING; 00338 chain = new_chain(); 00339 add_chain(part, chain); 00340 00341 } 00342 else if (strcmp(key, "LINE") == 0) { 00343 G_debug(4, " LINE >"); 00344 elem = new_line(); 00345 add_element(chain, elem); 00346 read_coor(fp, elem); 00347 00348 } 00349 else if (strcmp(key, "ARC") == 0) { 00350 G_debug(4, " ARC"); 00351 ret = 00352 sscanf(data, "%lf %lf %lf %lf %lf %c", &x, &y, &rad, &ang1, 00353 &ang2, &clock); 00354 if (ret < 5) { 00355 sprintf(buf, "Incorrect arc definition: '%s'", buf); 00356 return (err(fp, symb, buf)); 00357 } 00358 if (ret == 6 && (clock == 'c' || clock == 'C')) 00359 i = 1; 00360 else 00361 i = 0; 00362 elem = new_arc(x, y, rad, ang1, ang2, i); 00363 add_element(chain, elem); 00364 00365 } 00366 else if (strcmp(key, "END") == 0) { 00367 switch (current) { 00368 case OBJ_STRING: 00369 G_debug(4, " STRING END"); 00370 current = OBJ_NONE; 00371 break; 00372 case OBJ_POLYGON: 00373 G_debug(4, " POLYGON END"); 00374 current = OBJ_NONE; 00375 break; 00376 case OBJ_RING: 00377 G_debug(4, " RING END"); 00378 current = OBJ_POLYGON; 00379 break; 00380 } 00381 } 00382 else if (strcmp(key, "COLOR") == 0) { 00383 if (G_strcasecmp(data, "NONE") == 0) { 00384 part->color.color = S_COL_NONE; 00385 } 00386 else if (sscanf(data, "%d %d %d", &r, &g, &b) == 3) { 00387 if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) 00388 G_warning(_("Incorrect symbol color: '%s', using default."), 00389 buf); 00390 else { 00391 fr = r / 255.0; 00392 fg = g / 255.0; 00393 fb = b / 255.0; 00394 part->color.color = S_COL_DEFINED; 00395 part->color.r = r; 00396 part->color.g = g; 00397 part->color.b = b; 00398 part->color.fr = fr; 00399 part->color.fg = fg; 00400 part->color.fb = fb; 00401 G_debug(4, " color [%d %d %d] = [%.3f %.3f %.3f]", r, g, 00402 b, fr, fg, fb); 00403 } 00404 } 00405 else { 00406 G_warning(_("Incorrect symbol color: '%s', using default."), 00407 buf); 00408 } 00409 } 00410 else if (strcmp(key, "FCOLOR") == 0) { 00411 if (G_strcasecmp(data, "NONE") == 0) { 00412 part->fcolor.color = S_COL_NONE; 00413 } 00414 else if (sscanf(data, "%d %d %d", &r, &g, &b) == 3) { 00415 if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) 00416 G_warning(_("Incorrect symbol color: '%s', using default."), 00417 buf); 00418 else { 00419 fr = r / 255.0; 00420 fg = g / 255.0; 00421 fb = b / 255.0; 00422 part->fcolor.color = S_COL_DEFINED; 00423 part->fcolor.r = r; 00424 part->fcolor.g = g; 00425 part->fcolor.b = b; 00426 part->fcolor.fr = fr; 00427 part->fcolor.fg = fg; 00428 part->fcolor.fb = fb; 00429 G_debug(4, " color [%d %d %d] = [%.3f %.3f %.3f]", r, g, 00430 b, fr, fg, fb); 00431 } 00432 } 00433 else { 00434 G_warning(_("Incorrect symbol color: '%s', using default."), 00435 buf); 00436 } 00437 } 00438 else { 00439 sprintf(buf, "Unknown keyword in symbol: '%s'", buf); 00440 return (err(fp, symb, buf)); 00441 break; 00442 } 00443 } 00444 00445 /* Debug output */ 00446 00447 G_debug(3, "Number of parts: %d", symb->count); 00448 for (i = 0; i < symb->count; i++) { 00449 part = symb->part[i]; 00450 G_debug(4, " Part %d: type: %d number of chains: %d", i, part->type, 00451 part->count); 00452 G_debug(4, " color: %d: fcolor: %d", part->color.color, 00453 part->fcolor.color); 00454 for (j = 0; j < part->count; j++) { 00455 chain = part->chain[j]; 00456 G_debug(4, " Chain %d: number of elements: %d", j, 00457 chain->count); 00458 for (k = 0; k < chain->count; k++) { 00459 elem = chain->elem[k]; 00460 G_debug(4, " Element %d: type: %d", k, elem->type); 00461 if (elem->type == S_LINE) { 00462 G_debug(4, " Number of points %d", 00463 elem->coor.line.count); 00464 for (l = 0; l < elem->coor.line.count; l++) { 00465 G_debug(4, " x, y: %f %f", 00466 elem->coor.line.x[l], elem->coor.line.y[l]); 00467 } 00468 } 00469 else { 00470 G_debug(4, " arc r = %f", elem->coor.arc.r); 00471 } 00472 } 00473 } 00474 } 00475 00476 fclose(fp); 00477 00478 return symb; 00479 }