GRASS Programmer's Manual  6.4.2(2012)
symbol/read.c
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines