GRASS Programmer's Manual  6.4.1(2011)
cats.c
Go to the documentation of this file.
00001 
00002 /**********************************************************************
00003  *
00004  * Code in this file works with category files.  There are two formats:
00005  * Pre 3.0 direct category encoding form:
00006  * 
00007  *    2 categories
00008  *    Map Title
00009  *    Elevation: 1000.00 to 1005.00 feet
00010  *    Elevation: 1005.00 to 1010.00 feet
00011  *    Elevation: 1010.00 to 1015.00 feet
00012  *
00013  * 3.0 format
00014  * 
00015  *    # 2 categories
00016  *    Map Title
00017  *    Elevation: $1.2 to $2.2 feet       ## Format Statement
00018  *    5.0 1000 5.0 1005                  ## Coefficients
00019  *
00020  * The coefficient line can be followed by explicit category labels
00021  * which override the format label generation.
00022  *    0:no data
00023  *    2:   .
00024  *    5:   .                             ## explicit category labels
00025  *    7:   .
00026  * explicit labels can be also of the form:
00027  *    5.5:5:9 label description
00028  *    or
00029  *    15:30  label description
00030  *
00031  * In the format line
00032  *   $1 refers to the value num*5.0+1000 (ie, using the first 2 coefficients)
00033  *   $2 refers to the value num*5.0+1005 (ie, using the last 2 coefficients)
00034  *
00035  *   $1.2 will print $1 with 2 decimal places.
00036  *
00037  * Also, the form $?xxx$yyy$ translates into yyy if the category is 1, xxx 
00038  * otherwise. The $yyy$ is optional. Thus
00039  *
00040  *   $1 meter$?s
00041  *
00042  * will become: 1 meter (for category 1)
00043  *              2 meters (for category 2), etc.
00044  *
00045  * The format and coefficients above would be used to generate the
00046  * following statement in creation of the format appropriate category
00047  * string for category "num":
00048  *
00049  *   sprintf(buff,"Elevation: %.2f to %.2f feet", num*5.0+1000, num*5.0*1005)
00050  *
00051  * Note: while both the format and coefficent lins must be present
00052  *       a blank line for the fmt will effectively suppress automatic
00053  *       label generation
00054  *
00055  * Note: quant rules of Categories structures are heavily dependent
00056  * on the fact that rules are stored in the same order they are entered.
00057  * since i-th rule and i-th label are entered at the same time, we
00058  * know that i-th rule maps fp range to i, thus we know for sure
00059  * that cats.labels[i] corresponds to i-th quant rule
00060  * 
00061  **********************************************************************
00062  *
00063  *  G_read_[raster]_cats (name, mapset, pcats)
00064  *      char *name                   name of cell file
00065  *      char *mapset                 mapset that cell file belongs to
00066  *      struct Categories *pcats     structure to hold category info
00067  *
00068  *  Reads the category information associated with cell file "name"
00069  *  in mapset "mapset" into the structure "pcats".
00070  *
00071  *  returns:    0  if successful
00072  *             -1  on fail
00073  *
00074  *  note:   a warning message is printed if the file is
00075  *          "missing" or "invalid".
00076  **********************************************************************
00077  *
00078  *  G_copy_raster_cats (pcats_to, pcats_from)
00079  *      struct Categories *pcats_to
00080  *      const struct Categories *pcats_from
00081  *
00082  *  Allocates NEW space for quant rules and labels and copies
00083  *  all info from "from" cats to "to" cats
00084  *
00085  *  returns:    0  if successful
00086  *             -1  on fail
00087  *
00088  **********************************************************************
00089  *
00090  *  G_read_vector_cats (name, mapset, pcats)
00091  *      char *name                   name of vector map
00092  *      char *mapset                 mapset that vector map belongs to
00093  *      struct Categories *pcats     structure to hold category info
00094  *
00095  *
00096  *  returns:    0  if successful
00097  *             -1  on fail
00098  *
00099  *  note:   a warning message is printed if the file is
00100  *          "missing" or "invalid".
00101  **********************************************************************
00102  * Returns pointer to a string describing category.
00103  **********************************************************************
00104  *
00105  *  G_number_of_cats(name, mapset)
00106  *  returns the largest category number in the map.
00107  *  -1 on error
00108  *  WARING: do not use for fp maps!
00109  **********************************************************************
00110  *
00111  * char *
00112  * G_get_c/f/d_raster_cat (num, pcats)
00113  *      [F/D]CELL *val               pointer to cell value 
00114  *      struct Categories *pcats     structure to hold category info
00115  *
00116  * Returns pointer to a string describing category.
00117  *
00118  **********************************************************************
00119  *
00120  * char *
00121  * G_get_raster_cat (val, pcats, data_type)
00122  *      void *val               pointer to cell value 
00123  *      struct Categories *pcats     structure to hold category info
00124  *      RASTER_MAP_TYPE data_type    type of raster cell
00125  *
00126  * Returns pointer to a string describing category.
00127  *
00128  **********************************************************************
00129  *
00130  * char *
00131  * G_get_ith_c/f/d_raster_cat (pcats, i, rast1, rast2)
00132  *      [F/D]CELL *rast1, *rast2      cat range
00133  *      struct Categories *pcats     structure to hold category info
00134  *
00135  * Returns pointer to a string describing category.
00136  *
00137  **********************************************************************
00138  *
00139  * int
00140  * G_number_of_raster_cats (pcats)
00141  *      struct Categories *pcats     structure to hold category info
00142  *
00143  * Returns pcats->ncats number of labels
00144  *
00145  **********************************************************************
00146  *
00147  * char *
00148  * G_get_ith_raster_cat (pcats, i, rast1, rast2, data_type)
00149  *      void *rast1, *rast2      cat range
00150  *      struct Categories *pcats     structure to hold category info
00151  *      RASTER_MAP_TYPE data_type    type of raster cell
00152  *
00153  * Returns pointer to a string describing category.
00154  *
00155  **********************************************************************
00156  *
00157  * char *
00158  * G_get_[raster]_cats_title (pcats)
00159  *      struct Categories *pcats     structure to hold category info
00160  *
00161  * Returns pointer to a string with title
00162  *
00163  **********************************************************************
00164  *
00165  * G_init_cats (ncats, title, pcats)
00166  *      CELL ncats                   number of categories
00167  *      char *title                  cell title
00168  *      struct Categories *pcats     structure to hold category info
00169  *
00170  * Initializes the cats structure for subsequent calls to G_set_cat()
00171  **********************************************************************
00172  *
00173  * G_unmark_raster_cats (pcats)
00174  *      struct Categories *pcats     structure to hold category info
00175  *
00176  * initialize cats.marks: the statistics of how many values of map
00177  * have each label
00178  *
00179  **********************************************************************
00180  *
00181  * G_rewind_raster_cats (pcats)
00182  *      struct Categories *pcats     structure to hold category info
00183  *
00184  * after calll to this function G_get_next_marked_raster_cat() returns
00185  * rhe first marked cat label.
00186  *
00187  **********************************************************************
00188  *
00189  * char* G_get_next_marked_raster_cat(pcats, rast1, rast2, stats, data_type)
00190  *    struct Categories *pcats     structure to hold category info
00191  *    void *rast1, *rast2;         pointers to raster range
00192  *    long *stats;
00193  *    RASTER_MAP_TYPE  data_type
00194  *
00195  *    returns the next marked label.
00196  *    NULL if none found
00197  *
00198  **********************************************************************
00199  *
00200  * char* G_get_next_marked_f/d/craster_cat(pcats, rast1, rast2, stats)
00201  *    struct Categories *pcats     structure to hold category info
00202  *    [D/F]CELL *rast1, *rast2;    pointers to raster range
00203  *    long *stats;
00204  *
00205  *    returns the next marked label.
00206  *    NULL if none found
00207  *
00208  **********************************************************************
00209  *
00210  * G_mark_raster_cats (rast_row, ncols, pcats, data_type)
00211  *      void *raster_row;            raster row to update stats
00212  *      struct Categories *pcats     structure to hold category info
00213  *      RASTER_MAP_TYPE data_type;
00214  * Finds the index of label for each raster cell in a row, and
00215  * increases pcats->marks[index]
00216  * Note: if there are no explicit cats: only rules for cats, no 
00217  * marking is done.
00218  *
00219  **********************************************************************
00220  *
00221  * G_mark_c/d/f_raster_cats (rast_row, ncols, pcats)
00222  *      int ncols;
00223  *      [D?F]CELL *raster_row;            raster row to update stats
00224  *      struct Categories *pcats     structure to hold category info
00225  *
00226  * Finds the index of label for each raster cell in a row, and
00227  * increases pcats->marks[index]
00228  *
00229  **********************************************************************
00230  *
00231  * G_init_raster_cats (title, pcats)
00232  *      char *title                  cell title
00233  *      struct Categories *pcats     structure to hold category info
00234  *
00235  * Initializes the cats structure for subsequent calls to G_set_cat()
00236  *
00237  **********************************************************************
00238  *
00239  * G_set_[raster]_cats_fmt (fmt, m1, a1, m2, a2, pcats)
00240  *      char *fmt                    user form of the equation format
00241  *      float m1,a1,m2,a2            coefficients
00242  *      struct Categories *pcats     structure to hold category info
00243  *
00244  * configures the cats structure for the equation. Must be called
00245  * after G_init_cats().
00246  *
00247  **********************************************************************
00248  *
00249  * G_set_[raster]_cats_title (title, pcats)
00250  *      char *title                  cell file title
00251  *      struct Categories *pcats     structure holding category info
00252  *
00253  * Store title as cell file in cats structure
00254  * Returns nothing.
00255  *
00256  **********************************************************************
00257  *
00258  * G_set_cat (num, label, pcats)
00259  *      CELL num                     category number
00260  *      char *label                  category label
00261  *      struct Categories *pcats     structure to hold category info
00262  *
00263  * Adds the string buff to represent category "num" in category structure
00264  * pcats.
00265  *
00266  * Returns: 0 is cat is null value -1 too many cats, 1 ok.
00267  *
00268  **********************************************************************
00269  *
00270  * G_set_[f/d/c]_raster_cat (&val1, &val2, label, pcats)
00271  *      [D/F]CELL *val1, *val2;      pointers to raster values
00272  *      char *label                  category label
00273  *      struct Categories *pcats     structure to hold category info
00274  *
00275  * Adds the label for range val1 through val2 in category structure
00276  * pcats.
00277  *
00278  * Returns: 0 if cat is null value -1 too many cats, 1 ok.
00279  *
00280  **********************************************************************
00281  *
00282  * G_set_raster_cat (val1, val2, label, pcats, data_type)
00283  *      void *val1, *val2;           pointers to raster values
00284  *      char *label                  category label
00285  *      struct Categories *pcats     structure to hold category info
00286  *      RASTER_MAP_TYPE data_type    type of raster cell
00287  *
00288  * Adds the label for range val1 through val2 in category structure
00289  * pcats.
00290  *
00291  * Returns: 0 if cat is null value -1 too many cats, 1 ok.
00292  *
00293  **********************************************************************
00294  *
00295  *  G_write_[raster]_cats (name, pcats)
00296  *      char *name                   name of cell file
00297  *      struct Categories *pcats     structure holding category info
00298  *
00299  *  Writes the category information associated with cell file "name"
00300  *  into current mapset from the structure "pcats".
00301  *
00302  *   returns:    1  if successful
00303  *              -1  on fail
00304  **********************************************************************
00305  *
00306  *  G_write_vector_cats (name, pcats)
00307  *      char *name                   name of vector map
00308  *      struct Categories *pcats     structure holding category info
00309  *
00310  *  Writes the category information associated with vector map "name"
00311  *  into current mapset from the structure "pcats".
00312  *
00313  *   returns:    1  if successful
00314  *              -1  on fail
00315  **********************************************************************
00316  *
00317  * G_free_[raster]_cats (pcats)
00318  *      struct Categories *pcats     structure holding category info
00319  *
00320  * Releases memory allocated for the cats structure
00321  **********************************************************************/
00322 
00323 #include <stdlib.h>
00324 #include <string.h>
00325 #include <grass/gis.h>
00326 #include <grass/glocale.h>
00327 
00328 static int get_cond(char **, char *, DCELL);
00329 static int get_fmt(char **, char *, int *);
00330 static int cmp(const void *, const void *);
00331 
00332 
00347 int G_read_cats(const char *name,
00348                 const char *mapset, struct Categories *pcats)
00349 {
00350     return G_read_raster_cats(name, mapset, pcats);
00351 }
00352 
00353 
00365 int G_read_raster_cats(const char *name,
00366                        const char *mapset, struct Categories *pcats)
00367 {
00368     char *type;
00369 
00370     switch (G__read_cats("cats", name, mapset, pcats, 1)) {
00371     case -2:
00372         type = "missing";
00373         break;
00374     case -1:
00375         type = "invalid";
00376         break;
00377     default:
00378         return 0;
00379     }
00380 
00381     G_warning(_("category support for [%s] in mapset [%s] %s"),
00382               name, mapset, type);
00383     return -1;
00384 }
00385 
00386 
00401 int G_read_vector_cats(const char *name,
00402                        const char *mapset, struct Categories *pcats)
00403 {
00404     char *type;
00405 
00406     switch (G__read_cats("dig_cats", name, mapset, pcats, 1)) {
00407     case -2:
00408         type = "missing";
00409         break;
00410     case -1:
00411         type = "invalid";
00412         break;
00413     default:
00414         return 0;
00415     }
00416 
00417     G_warning(_("category support for vector map [%s] in mapset [%s] %s"),
00418               name, mapset, type);
00419     return -1;
00420 }
00421 
00422 CELL G_number_of_cats(const char *name, const char *mapset)
00423 {
00424     struct Range range;
00425     CELL min, max;
00426 
00427     /* return the max category number */
00428     if (G_read_range(name, mapset, &range) < 0)
00429         return -1;
00430     G_get_range_min_max(&range, &min, &max);
00431     if (G_is_c_null_value(&max))
00432         max = 0;
00433     return max;
00434 }
00435 
00436 CELL G__read_cats(const char *element,
00437                   const char *name,
00438                   const char *mapset, struct Categories * pcats, int full)
00439 {
00440     FILE *fd;
00441     char buff[1024];
00442     CELL cat;
00443     DCELL val1, val2;
00444     int old = 0, fp_map;
00445     long num = -1;
00446 
00447 
00448     if (strncmp(element, "dig", 3) == 0)
00449         fp_map = 0;
00450     else
00451         fp_map = G_raster_map_is_fp(name, mapset);
00452 
00453     if (!(fd = G_fopen_old(element, name, mapset)))
00454         return -2;
00455 
00456     /* Read the number of categories */
00457     if (G_getl(buff, sizeof buff, fd) == 0)
00458         goto error;
00459 
00460     if (sscanf(buff, "# %ld", &num) == 1)
00461         old = 0;
00462     else if (sscanf(buff, "%ld", &num) == 1)
00463         old = 1;
00464 
00465     if (!full) {
00466         fclose(fd);
00467         if (num < 0)
00468             return 0;           /* coorect */
00469         return (CELL) num;
00470     }
00471 
00472     /* Read the title for the file */
00473     if (G_getl(buff, sizeof buff, fd) == 0)
00474         goto error;
00475     G_strip(buff);
00476     /*    G_ascii_check(buff) ; */
00477 
00478     G_init_raster_cats(buff, pcats);
00479     if (num >= 0)
00480         pcats->num = num;
00481 
00482     if (!old) {
00483         char fmt[256];
00484         float m1, a1, m2, a2;
00485 
00486         if (G_getl(fmt, sizeof fmt, fd) == 0)
00487             goto error;
00488         /* next line contains equation coefficients */
00489         if (G_getl(buff, sizeof buff, fd) == 0)
00490             goto error;
00491         if (sscanf(buff, "%f %f %f %f", &m1, &a1, &m2, &a2) != 4)
00492             goto error;
00493         G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
00494     }
00495 
00496     /* Read all category names */
00497     for (cat = 0;; cat++) {
00498         char label[1024];
00499 
00500         if (G_getl(buff, sizeof buff, fd) == 0)
00501             break;
00502         if (old)
00503             G_set_cat(cat, buff, pcats);
00504         else {
00505             *label = 0;
00506             if (sscanf(buff, "%1s", label) != 1)
00507                 continue;
00508             if (*label == '#')
00509                 continue;
00510             *label = 0;
00511             /* for fp maps try to read a range of data */
00512             if (fp_map
00513                 && sscanf(buff, "%lf:%lf:%[^\n]", &val1, &val2, label) == 3)
00514                 G_set_raster_cat(&val1, &val2, label, pcats, DCELL_TYPE);
00515             else if (sscanf(buff, "%d:%[^\n]", &cat, label) >= 1)
00516                 G_set_raster_cat(&cat, &cat, label, pcats, CELL_TYPE);
00517             else if (sscanf(buff, "%lf:%[^\n]", &val1, label) >= 1)
00518                 G_set_raster_cat(&val1, &val1, label, pcats, DCELL_TYPE);
00519             else
00520                 goto error;
00521         }
00522     }
00523 
00524     fclose(fd);
00525     return 0;
00526   error:
00527     fclose(fd);
00528     return -1;
00529 }
00530 
00531 
00545 char *G_get_cats_title(const struct Categories *pcats)
00546 {
00547     return G_get_raster_cats_title(pcats);
00548 }
00549 
00550 
00560 char *G_get_raster_cats_title(const struct Categories *pcats)
00561 {
00562     static char *none = "";
00563 
00564     return pcats->title ? pcats->title : none;
00565 }
00566 
00567 
00583 char *G_get_cat(CELL num, struct Categories *pcats)
00584 {
00585     return G_get_c_raster_cat(&num, pcats);
00586 }
00587 
00588 
00600 char *G_get_c_raster_cat(CELL * rast, struct Categories *pcats)
00601 {
00602     return G_get_raster_cat(rast, pcats, CELL_TYPE);
00603 }
00604 
00605 
00617 char *G_get_f_raster_cat(FCELL * rast, struct Categories *pcats)
00618 {
00619     return G_get_raster_cat(rast, pcats, FCELL_TYPE);
00620 }
00621 
00622 
00634 char *G_get_d_raster_cat(DCELL * rast, struct Categories *pcats)
00635 {
00636     return G_get_raster_cat(rast, pcats, DCELL_TYPE);
00637 }
00638 
00639 
00652 char *G_get_raster_cat(void *rast,
00653                        struct Categories *pcats, RASTER_MAP_TYPE data_type)
00654 {
00655     static char label[1024];
00656     char *f, *l, *v;
00657     CELL i;
00658     DCELL val;
00659     float a[2];
00660     char fmt[30], value_str[30];
00661 
00662     if (G_is_null_value(rast, data_type)) {
00663         sprintf(label, "no data");
00664         return label;
00665     }
00666 
00667     /* first search the list of labels */
00668     *label = 0;
00669     val = G_get_raster_value_d(rast, data_type);
00670     i = G_quant_get_cell_value(&pcats->q, val);
00671 
00672     G_debug(5, "G_get_raster_cat(): val %lf found i %d", val, i);
00673 
00674     if (!G_is_c_null_value(&i) && i < pcats->ncats) {
00675         if (pcats->labels[i] != NULL)
00676             return pcats->labels[i];
00677         return label;
00678     }
00679 
00680     /* generate the label */
00681     if ((f = pcats->fmt) == NULL)
00682         return label;
00683 
00684     a[0] = (float)val *pcats->m1 + pcats->a1;
00685     a[1] = (float)val *pcats->m2 + pcats->a2;
00686 
00687     l = label;
00688     while (*f) {
00689         if (*f == '$') {
00690             f++;
00691             if (*f == '$')
00692                 *l++ = *f++;
00693             else if (*f == '?') {
00694                 f++;
00695                 get_cond(&f, v = value_str, val);
00696                 while (*v)
00697                     *l++ = *v++;
00698             }
00699             else if (get_fmt(&f, fmt, &i)) {
00700                 sprintf(v = value_str, fmt, a[i]);
00701                 while (*v)
00702                     *l++ = *v++;
00703             }
00704             else
00705                 *l++ = '$';
00706         }
00707         else {
00708             *l++ = *f++;
00709         }
00710     }
00711     *l = 0;
00712     return label;
00713 }
00714 
00715 
00731 int G_unmark_raster_cats(struct Categories *pcats)
00732 {                               /* structure to hold category info */
00733     register int i;
00734 
00735     for (i = 0; i < pcats->ncats; i++)
00736         pcats->marks[i] = 0;
00737     return 0;
00738 }
00739 
00740 
00755 int G_mark_c_raster_cats(CELL * rast_row,       /* raster row to update stats */
00756                          int ncols, struct Categories *pcats)
00757 {                               /* structure to hold category info */
00758     G_mark_raster_cats(rast_row, ncols, pcats, CELL_TYPE);
00759     return 0;
00760 }
00761 
00762 
00777 int G_mark_f_raster_cats(FCELL * rast_row,      /* raster row to update stats */
00778                          int ncols, struct Categories *pcats)
00779 {                               /* structure to hold category info */
00780     G_mark_raster_cats(rast_row, ncols, pcats, FCELL_TYPE);
00781     return 0;
00782 }
00783 
00784 
00799 int G_mark_d_raster_cats(DCELL * rast_row,      /* raster row to update stats */
00800                          int ncols, struct Categories *pcats)
00801 {                               /* structure to hold category info */
00802     G_mark_raster_cats(rast_row, ncols, pcats, DCELL_TYPE);
00803     return 0;
00804 }
00805 
00806 
00823 int G_mark_raster_cats(void *rast_row,  /* raster row to update stats */
00824                        int ncols, struct Categories *pcats,     /* structure to hold category info */
00825                        RASTER_MAP_TYPE data_type)
00826 {
00827     CELL i;
00828 
00829     while (ncols-- > 0) {
00830         i = G_quant_get_cell_value(&pcats->q,
00831                                    G_get_raster_value_d(rast_row, data_type));
00832         if (G_is_c_null_value(&i))
00833             continue;
00834         if (i > pcats->ncats)
00835             return -1;
00836         pcats->marks[i]++;
00837         rast_row = G_incr_void_ptr(rast_row, G_raster_size(data_type));
00838     }
00839     return 1;
00840 }
00841 
00842 
00854 int G_rewind_raster_cats(struct Categories *pcats)
00855 {
00856     pcats->last_marked_rule = -1;
00857     return 0;
00858 }
00859 
00860 char *G_get_next_marked_d_raster_cat(struct Categories *pcats,  /* structure to hold category info */
00861                                      DCELL * rast1, DCELL * rast2,      /* pointers to raster range */
00862                                      long *count)
00863 {
00864     char *descr = NULL;
00865     int found, i;
00866 
00867     found = 0;
00868     /* pcats->ncats should be == G_quant_nof_rules(&pcats->q) */
00869     /* DEBUG
00870        fprintf (stderr, "last marked %d nrules %d\n", pcats->last_marked_rule, G_quant_nof_rules(&pcats->q));
00871      */
00872     for (i = pcats->last_marked_rule + 1; i < G_quant_nof_rules(&pcats->q);
00873          i++) {
00874         descr = G_get_ith_d_raster_cat(pcats, i, rast1, rast2);
00875         /* DEBUG fprintf (stderr, "%d %d\n", i, pcats->marks[i]); */
00876         if (pcats->marks[i]) {
00877             found = 1;
00878             break;
00879         }
00880     }
00881 
00882     if (!found)
00883         return NULL;
00884 
00885     *count = pcats->marks[i];
00886     pcats->last_marked_rule = i;
00887     return descr;
00888 }
00889 
00890 char *G_get_next_marked_c_raster_cat(struct Categories *pcats,  /* structure to hold category info */
00891                                      CELL * rast1, CELL * rast2,        /* pointers to raster range */
00892                                      long *count)
00893 {
00894     return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
00895                                         CELL_TYPE);
00896 }
00897 
00898 char *G_get_next_marked_f_raster_cat(struct Categories *pcats,  /* structure to hold category info */
00899                                      FCELL * rast1, FCELL * rast2,      /* pointers to raster range */
00900                                      long *count)
00901 {
00902     return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
00903                                         FCELL_TYPE);
00904 }
00905 
00906 char *G_get_next_marked_raster_cat(struct Categories *pcats,    /* structure to hold category info */
00907                                    void *rast1, void *rast2,    /* pointers to raster range */
00908                                    long *count, RASTER_MAP_TYPE data_type)
00909 {
00910     DCELL val1, val2;
00911     char *lab;
00912 
00913     lab = G_get_next_marked_d_raster_cat(pcats, &val1, &val2, count);
00914     G_set_raster_value_d(rast1, val1, data_type);
00915     G_set_raster_value_d(rast2, val2, data_type);
00916     return lab;
00917 }
00918 
00919 static int get_fmt(char **f, char *fmt, int *i)
00920 {
00921     char *ff;
00922 
00923     ff = *f;
00924     if (*ff == 0)
00925         return 0;
00926     if (*ff == '$') {
00927         *f = ff + 1;
00928         return 0;
00929     }
00930     switch (*ff++) {
00931     case '1':
00932         *i = 0;
00933         break;
00934     case '2':
00935         *i = 1;
00936         break;
00937     default:
00938         return 0;
00939     }
00940     *fmt++ = '%';
00941     *fmt++ = '.';
00942     if (*ff++ != '.') {
00943         *f = ff - 1;
00944         *fmt++ = '0';
00945         *fmt++ = 'f';
00946         *fmt = 0;
00947         return 1;
00948     }
00949     *fmt = '0';
00950     while (*ff >= '0' && *ff <= '9')
00951         *fmt++ = *ff++;
00952     *fmt++ = 'f';
00953     *fmt = 0;
00954     *f = ff;
00955     return 1;
00956 }
00957 
00958 static int get_cond(char **f, char *value, DCELL val)
00959 {
00960     char *ff;
00961 
00962     ff = *f;
00963     if (val == 1.) {
00964         while (*ff)
00965             if (*ff++ == '$')
00966                 break;
00967     }
00968 
00969     while (*ff)
00970         if (*ff == '$') {
00971             ff++;
00972             break;
00973         }
00974         else
00975             *value++ = *ff++;
00976 
00977     if (val != 1.) {
00978         while (*ff)
00979             if (*ff++ == '$')
00980                 break;
00981     }
00982     *value = 0;
00983     *f = ff;
00984 
00985     return 0;
00986 }
00987 
00988 
01001 int G_set_cat(CELL num, char *label, struct Categories *pcats)
01002 {
01003     CELL tmp = num;
01004 
01005     return G_set_c_raster_cat(&tmp, &tmp, label, pcats);
01006 }
01007 
01008 
01021 int G_set_c_raster_cat(CELL * rast1, CELL * rast2,
01022                        char *label, struct Categories *pcats)
01023 {
01024     return G_set_raster_cat(rast1, rast2, label, pcats, CELL_TYPE);
01025 }
01026 
01027 
01040 int G_set_f_raster_cat(FCELL * rast1, FCELL * rast2,
01041                        char *label, struct Categories *pcats)
01042 {
01043     return G_set_raster_cat(rast1, rast2, label, pcats, FCELL_TYPE);
01044 }
01045 
01046 
01059 int G_set_d_raster_cat(DCELL * rast1, DCELL * rast2,
01060                        char *label, struct Categories *pcats)
01061 {
01062     long len;
01063     DCELL dtmp1, dtmp2;
01064     int i;
01065     char *descr;
01066 
01067     /* DEBUG fprintf(stderr,"G_set_d_raster_cat(rast1 = %p,rast2 = %p,label = '%s',pcats = %p)\n",
01068        rast1,rast2,label,pcats); */
01069     if (G_is_d_null_value(rast1))
01070         return 0;
01071     if (G_is_d_null_value(rast2))
01072         return 0;
01073     /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): adding quant rule: %f %f %d %d\n", *rast1, *rast2, pcats->ncats, pcats->ncats); */
01074     /* the set_cat() functions are used in many places to reset the labels
01075        for the range (or cat) with existing label. In this case we don't
01076        want to store both rules with identical range even though the result
01077        of get_cat() will be correct, since it will use rule added later.
01078        we don't want to overuse memory and we don't want rules which are
01079        not used to be writen out in cats file. So we first look if
01080        the label for this range has been sen, and if it has, overwrite it */
01081 
01082     for (i = 0; i < pcats->ncats; i++) {
01083         descr = G_get_ith_d_raster_cat(pcats, i, &dtmp1, &dtmp2);
01084         if ((dtmp1 == *rast1 && dtmp2 == *rast2)
01085             || (dtmp1 == *rast2 && dtmp2 == *rast1)) {
01086             if (pcats->labels[i] != NULL)
01087                 G_free(pcats->labels[i]);
01088             pcats->labels[i] = G_store(label);
01089             G_newlines_to_spaces(pcats->labels[i]);
01090             G_strip(pcats->labels[i]);
01091             return 1;
01092         }
01093     }
01094     /* when rule for this range does not exist */
01095     /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): New rule: adding %d %p\n", i, pcats->labels); */
01096     G_quant_add_rule(&pcats->q, *rast1, *rast2, pcats->ncats, pcats->ncats);
01097     pcats->ncats++;
01098     if (pcats->nalloc < pcats->ncats) {
01099         /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): need more space nalloc = %d ncats = %d\n", pcats->nalloc,pcats->ncats); */
01100         len = (pcats->nalloc + 256) * sizeof(char *);
01101         /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): allocating %d labels(%d)\n", pcats->nalloc + 256,(int)len); */
01102         if (len != (int)len) {  /* make sure len doesn't overflow int */
01103             pcats->ncats--;
01104             return -1;
01105         }
01106         /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): pcats->nalloc = %d, pcats->labels = (%p), len = %d\n",pcats->nalloc,pcats->labels,(int)len); */
01107         if (pcats->nalloc) {
01108             /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): Realloc-ing pcats->labels (%p)\n",pcats->labels); */
01109             pcats->labels =
01110                 (char **)G_realloc((char *)pcats->labels, (int)len);
01111         }
01112         else {
01113             /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): alloc-ing new labels pointer array\n"); */
01114             pcats->labels = (char **)G_malloc((int)len);
01115         }
01116         /* fflush(stderr); */
01117         /* DEBUG fprintf (stderr, "G_set_d_raster_cats(): allocating %d marks(%d)\n", pcats->nalloc + 256,(int)len); */
01118         len = (pcats->nalloc + 256) * sizeof(int);
01119         if (len != (int)len) {  /* make sure len doesn't overflow int */
01120             pcats->ncats--;
01121             return -1;
01122         }
01123         if (pcats->nalloc)
01124             pcats->marks = (int *)G_realloc((char *)pcats->marks, (int)len);
01125         else
01126             pcats->marks = (int *)G_malloc((int)len);
01127         pcats->nalloc += 256;
01128     }
01129     /* DEBUG fprintf(stderr,"G_set_d_raster_cats(): store new label\n"); */
01130     pcats->labels[pcats->ncats - 1] = G_store(label);
01131     G_newlines_to_spaces(pcats->labels[pcats->ncats - 1]);
01132     G_strip(pcats->labels[pcats->ncats - 1]);
01133     /* DEBUG
01134        fprintf (stderr, "%d %s\n", pcats->ncats - 1, pcats->labels[pcats->ncats - 1]);
01135      */
01136     /* updates cats.num = max cat values. This is really just used in old
01137        raster programs, and I am doing it for backwards cmpatibility (Olga) */
01138     if ((CELL) * rast1 > pcats->num)
01139         pcats->num = (CELL) * rast1;
01140     if ((CELL) * rast2 > pcats->num)
01141         pcats->num = (CELL) * rast2;
01142     /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): done\n"); */
01143     /* DEBUG fflush(stderr); */
01144     return 1;
01145 }
01146 
01147 
01160 int G_set_raster_cat(void *rast1, void *rast2,
01161                      char *label,
01162                      struct Categories *pcats, RASTER_MAP_TYPE data_type)
01163 {
01164     DCELL val1, val2;
01165 
01166     val1 = G_get_raster_value_d(rast1, data_type);
01167     val2 = G_get_raster_value_d(rast2, data_type);
01168     return G_set_d_raster_cat(&val1, &val2, label, pcats);
01169 }
01170 
01171 
01185 int G_write_cats(char *name, struct Categories *cats)
01186 {
01187     return G__write_cats("cats", name, cats);
01188 }
01189 
01190 
01201 int G_write_raster_cats(char *name, struct Categories *cats)
01202 {
01203     return G__write_cats("cats", name, cats);
01204 }
01205 
01206 
01221 int G_write_vector_cats(char *name, struct Categories *cats)
01222 {
01223     return G__write_cats("dig_cats", name, cats);
01224 }
01225 
01226 int G__write_cats(char *element, char *name, struct Categories *cats)
01227 {
01228     FILE *fd;
01229     int i, fp_map;
01230     char *descr;
01231     DCELL val1, val2;
01232     char str1[100], str2[100];
01233 
01234     /* DEBUG fprintf(stderr,"G__write_cats(*element = '%s', name = '%s', cats = %p\n",element,name,cats); */
01235     if (!(fd = G_fopen_new(element, name)))
01236         return -1;
01237 
01238     /* write # cats - note # indicate 3.0 or later */
01239     fprintf(fd, "# %ld categories\n", (long)cats->num);
01240 
01241     /* title */
01242     fprintf(fd, "%s\n", cats->title != NULL ? cats->title : "");
01243 
01244     /* write format and coefficients */
01245     fprintf(fd, "%s\n", cats->fmt != NULL ? cats->fmt : "");
01246     fprintf(fd, "%.2f %.2f %.2f %.2f\n",
01247             cats->m1, cats->a1, cats->m2, cats->a2);
01248 
01249     /* if the map is integer or if this is a vector map, sort labels */
01250     if (strncmp(element, "dig", 3) == 0)
01251         fp_map = 0;
01252     else
01253         fp_map = G_raster_map_is_fp(name, G_mapset());
01254     /* DEBUG fprintf(stderr,"G__write_cats(): fp_map = %d\n",fp_map); */
01255     if (!fp_map)
01256         G_sort_cats(cats);
01257 
01258     /* write the cat numbers:label */
01259     for (i = 0; i < G_quant_nof_rules(&cats->q); i++) {
01260         descr = G_get_ith_d_raster_cat(cats, i, &val1, &val2);
01261         if ((cats->fmt && cats->fmt[0])
01262             || (descr && descr[0])) {
01263             if (val1 == val2) {
01264                 sprintf(str1, "%.10f", val1);
01265                 G_trim_decimal(str1);
01266                 fprintf(fd, "%s:%s\n", str1, descr != NULL ? descr : "");
01267             }
01268             else {
01269                 sprintf(str1, "%.10f", val1);
01270                 G_trim_decimal(str1);
01271                 sprintf(str2, "%.10f", val2);
01272                 G_trim_decimal(str2);
01273                 fprintf(fd, "%s:%s:%s\n", str1, str2,
01274                         descr != NULL ? descr : "");
01275             }
01276         }
01277     }
01278     fclose(fd);
01279     /* DEBUG fprintf(stderr,"G__write_cats(): done\n"); */
01280     return (1);
01281 }
01282 
01283 
01298 char *G_get_ith_d_raster_cat(const struct Categories *pcats,
01299                              int i, DCELL * rast1, DCELL * rast2)
01300 {
01301     int index;
01302 
01303     if (i > pcats->ncats) {
01304         G_set_d_null_value(rast1, 1);
01305         G_set_d_null_value(rast2, 1);
01306         return "";
01307     }
01308     G_quant_get_ith_rule(&pcats->q, i, rast1, rast2, &index, &index);
01309     return pcats->labels[index];
01310 }
01311 
01312 
01327 char *G_get_ith_f_raster_cat(const struct Categories *pcats,
01328                              int i, void *rast1, void *rast2)
01329 {
01330     RASTER_MAP_TYPE data_type = FCELL_TYPE;
01331     char *tmp;
01332     DCELL val1, val2;
01333 
01334     tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
01335     G_set_raster_value_d(rast1, val1, data_type);
01336     G_set_raster_value_d(rast2, val2, data_type);
01337     return tmp;
01338 }
01339 
01340 
01355 char *G_get_ith_c_raster_cat(const struct Categories *pcats,
01356                              int i, void *rast1, void *rast2)
01357 {
01358     RASTER_MAP_TYPE data_type = CELL_TYPE;
01359     char *tmp;
01360     DCELL val1, val2;
01361 
01362     tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
01363     G_set_raster_value_d(rast1, val1, data_type);
01364     G_set_raster_value_d(rast2, val2, data_type);
01365     return tmp;
01366 }
01367 
01368 
01385 char *G_get_ith_raster_cat(const struct Categories *pcats, int i, void *rast1,
01386                            void *rast2, RASTER_MAP_TYPE data_type)
01387 {
01388     char *tmp;
01389     DCELL val1, val2;
01390 
01391     tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
01392     G_set_raster_value_d(rast1, val1, data_type);
01393     G_set_raster_value_d(rast2, val2, data_type);
01394     return tmp;
01395 }
01396 
01397 
01417 int G_init_cats(CELL num, const char *title, struct Categories *pcats)
01418 {
01419     G_init_raster_cats(title, pcats);
01420     pcats->num = num;
01421     return 0;
01422 }
01423 
01424 
01437 int G_init_raster_cats(const char *title, struct Categories *pcats)
01438 {
01439     G_set_raster_cats_title(title, pcats);
01440     pcats->labels = NULL;
01441     pcats->nalloc = 0;
01442     pcats->ncats = 0;
01443     pcats->num = 0;
01444     pcats->fmt = NULL;
01445     pcats->m1 = 0.0;
01446     pcats->a1 = 0.0;
01447     pcats->m2 = 0.0;
01448     pcats->a2 = 0.0;
01449     pcats->last_marked_rule = -1;
01450     G_quant_init(&pcats->q);
01451     return 0;
01452 }
01453 
01454 
01466 int G_set_cats_title(const char *title, struct Categories *pcats)
01467 {
01468     G_set_raster_cats_title(title, pcats);
01469     return 0;
01470 }
01471 
01472 
01483 int G_set_raster_cats_title(const char *title, struct Categories *pcats)
01484 {
01485     if (title == NULL)
01486         title = "";
01487     pcats->title = G_store(title);
01488     G_newlines_to_spaces(pcats->title);
01489     G_strip(pcats->title);
01490     return 0;
01491 }
01492 
01493 int G_set_cats_fmt(const char *fmt, double m1, double a1, double m2,
01494                    double a2, struct Categories *pcats)
01495 {
01496     G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
01497     return 0;
01498 }
01499 
01500 
01515 int G_set_raster_cats_fmt(const char *fmt, double m1, double a1, double m2,
01516                           double a2, struct Categories *pcats)
01517 {
01518     pcats->m1 = m1;
01519     pcats->a1 = a1;
01520     pcats->m2 = m2;
01521     pcats->a2 = a2;
01522 
01523     pcats->fmt = G_store(fmt);
01524     G_newlines_to_spaces(pcats->fmt);
01525     G_strip(pcats->fmt);
01526     return 0;
01527 }
01528 
01529 
01540 int G_free_cats(struct Categories *pcats)
01541 {
01542     G_free_raster_cats(pcats);
01543     return 0;
01544 }
01545 
01546 
01556 int G_free_raster_cats(struct Categories *pcats)
01557 {
01558     int i;
01559 
01560     if (pcats->title != NULL) {
01561         G_free(pcats->title);
01562         pcats->title = NULL;
01563     }
01564     if (pcats->fmt != NULL) {
01565         G_free(pcats->fmt);
01566         pcats->fmt = NULL;
01567     }
01568     if (pcats->ncats > 0) {
01569         for (i = 0; i < pcats->ncats; i++)
01570             if (pcats->labels[i] != NULL)
01571                 G_free(pcats->labels[i]);
01572         G_free(pcats->labels);
01573         G_free(pcats->marks);
01574         pcats->labels = NULL;
01575     }
01576     G_quant_free(&pcats->q);
01577     pcats->ncats = 0;
01578     pcats->nalloc = 0;
01579     return 0;
01580 }
01581 
01582 
01597 int
01598 G_copy_raster_cats(struct Categories *pcats_to,
01599                    const struct Categories *pcats_from)
01600 {
01601     int i;
01602     char *descr;
01603     DCELL d1, d2;
01604 
01605     G_init_raster_cats(pcats_from->title, pcats_to);
01606     for (i = 0; i < pcats_from->ncats; i++) {
01607         descr = G_get_ith_d_raster_cat(pcats_from, i, &d1, &d2);
01608         G_set_d_raster_cat(&d1, &d2, descr, pcats_to);
01609     }
01610     return 0;
01611 }
01612 
01613 int G_number_of_raster_cats(struct Categories *pcats)
01614 {
01615     return pcats->ncats;
01616 }
01617 
01618 static struct Categories save_cats;
01619 
01620 int G_sort_cats(struct Categories *pcats)
01621 {
01622     int *indexes, i, ncats;
01623     char *descr;
01624     DCELL d1, d2;
01625 
01626     if (pcats->ncats <= 1)
01627         return -1;
01628 
01629     ncats = pcats->ncats;
01630     /* DEBUG fprintf(stderr,"G_sort_cats(): Copying to save cats buffer\n"); */
01631     G_copy_raster_cats(&save_cats, pcats);
01632     G_free_raster_cats(pcats);
01633 
01634     indexes = (int *)G_malloc(sizeof(int) * ncats);
01635     for (i = 0; i < ncats; i++)
01636         indexes[i] = i;
01637 
01638     qsort(indexes, ncats, sizeof(int), cmp);
01639     G_init_raster_cats(save_cats.title, pcats);
01640     for (i = 0; i < ncats; i++) {
01641         descr = G_get_ith_d_raster_cat(&save_cats, indexes[i], &d1, &d2);
01642         /* DEBUG fprintf(stderr,"G_sort_cats(): Write sorted cats, pcats = %p pcats->labels = %p\n",pcats,pcats->labels); */
01643         G_set_d_raster_cat(&d1, &d2, descr, pcats);
01644         /* DEBUG fflush(stderr); */
01645     }
01646     G_free_raster_cats(&save_cats);
01647     /* DEBUG fprintf(stderr,"G_sort_cats(): Done\n"); */
01648     /* fflush(stderr); */
01649 
01650     return 0;
01651 }
01652 
01653 static int cmp(const void *aa, const void *bb)
01654 {
01655     const int *a = aa, *b = bb;
01656     DCELL min_rast1, min_rast2, max_rast1, max_rast2;
01657     CELL index;
01658 
01659     G_quant_get_ith_rule(&(save_cats.q), *a,
01660                          &min_rast1, &max_rast1, &index, &index);
01661     G_quant_get_ith_rule(&(save_cats.q), *b,
01662                          &min_rast2, &max_rast2, &index, &index);
01663     if (min_rast1 < min_rast2)
01664         return -1;
01665     if (min_rast1 > min_rast2)
01666         return 1;
01667     return 0;
01668 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines