1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645 |
- /**********************************************************************
- *
- * Code in this file works with category files. There are two formats:
- * Pre 3.0 direct category encoding form:
- *
- * 2 categories
- * Map Title
- * Elevation: 1000.00 to 1005.00 feet
- * Elevation: 1005.00 to 1010.00 feet
- * Elevation: 1010.00 to 1015.00 feet
- *
- * 3.0 format
- *
- * # 2 categories
- * Map Title
- * Elevation: $1.2 to $2.2 feet ## Format Statement
- * 5.0 1000 5.0 1005 ## Coefficients
- *
- * The coefficient line can be followed by explicit category labels
- * which override the format label generation.
- * 0:no data
- * 2: .
- * 5: . ## explicit category labels
- * 7: .
- * explicit labels can be also of the form:
- * 5.5:5:9 label description
- * or
- * 15:30 label description
- *
- * In the format line
- * $1 refers to the value num*5.0+1000 (ie, using the first 2 coefficients)
- * $2 refers to the value num*5.0+1005 (ie, using the last 2 coefficients)
- *
- * $1.2 will print $1 with 2 decimal places.
- *
- * Also, the form $?xxx$yyy$ translates into yyy if the category is 1, xxx
- * otherwise. The $yyy$ is optional. Thus
- *
- * $1 meter$?s
- *
- * will become: 1 meter (for category 1)
- * 2 meters (for category 2), etc.
- *
- * The format and coefficients above would be used to generate the
- * following statement in creation of the format appropriate category
- * string for category "num":
- *
- * sprintf(buff,"Elevation: %.2f to %.2f feet", num*5.0+1000, num*5.0*1005)
- *
- * Note: while both the format and coefficent lins must be present
- * a blank line for the fmt will effectively suppress automatic
- * label generation
- *
- * Note: quant rules of Categories structures are heavily dependent
- * on the fact that rules are stored in the same order they are entered.
- * since i-th rule and i-th label are entered at the same time, we
- * know that i-th rule maps fp range to i, thus we know for sure
- * that cats.labels[i] corresponds to i-th quant rule
- *
- **********************************************************************
- *
- * G_read_[raster]_cats (name, mapset, pcats)
- * const char *name name of cell file
- * const char *mapset mapset that cell file belongs to
- * struct Categories *pcats structure to hold category info
- *
- * Reads the category information associated with cell file "name"
- * in mapset "mapset" into the structure "pcats".
- *
- * returns: 0 if successful
- * -1 on fail
- *
- * note: a warning message is printed if the file is
- * "missing" or "invalid".
- **********************************************************************
- *
- * G_copy_raster_cats (pcats_to, pcats_from)
- * struct Categories *pcats_to
- * const struct Categories *pcats_from
- *
- * Allocates NEW space for quant rules and labels and copies
- * all info from "from" cats to "to" cats
- *
- * returns: 0 if successful
- * -1 on fail
- *
- **********************************************************************
- *
- * G_read_vector_cats (name, mapset, pcats)
- * const char *name name of vector map
- * const char *mapset mapset that vector map belongs to
- * struct Categories *pcats structure to hold category info
- *
- *
- * returns: 0 if successful
- * -1 on fail
- *
- * note: a warning message is printed if the file is
- * "missing" or "invalid".
- **********************************************************************
- * Returns pointer to a string describing category.
- **********************************************************************
- *
- * G_number_of_cats(name, mapset)
- * returns the largest category number in the map.
- * -1 on error
- * WARING: do not use for fp maps!
- **********************************************************************
- *
- * char *
- * G_get_c/f/d_raster_cat (num, pcats)
- * [F/D]CELL *val pointer to cell value
- * struct Categories *pcats structure to hold category info
- *
- * Returns pointer to a string describing category.
- *
- **********************************************************************
- *
- * char *
- * G_get_raster_cat (val, pcats, data_type)
- * void *val pointer to cell value
- * struct Categories *pcats structure to hold category info
- * RASTER_MAP_TYPE data_type type of raster cell
- *
- * Returns pointer to a string describing category.
- *
- **********************************************************************
- *
- * char *
- * G_get_ith_c/f/d_raster_cat (pcats, i, rast1, rast2)
- * [F/D]CELL *rast1, *rast2 cat range
- * struct Categories *pcats structure to hold category info
- *
- * Returns pointer to a string describing category.
- *
- **********************************************************************
- *
- * int
- * G_number_of_raster_cats (pcats)
- * struct Categories *pcats structure to hold category info
- *
- * Returns pcats->ncats number of labels
- *
- **********************************************************************
- *
- * char *
- * G_get_ith_raster_cat (pcats, i, rast1, rast2, data_type)
- * void *rast1, *rast2 cat range
- * struct Categories *pcats structure to hold category info
- * RASTER_MAP_TYPE data_type type of raster cell
- *
- * Returns pointer to a string describing category.
- *
- **********************************************************************
- *
- * char *
- * G_get_[raster]_cats_title (pcats)
- * struct Categories *pcats structure to hold category info
- *
- * Returns pointer to a string with title
- *
- **********************************************************************
- *
- * G_init_cats (ncats, title, pcats)
- * CELL ncats number of categories
- * const char *title cell title
- * struct Categories *pcats structure to hold category info
- *
- * Initializes the cats structure for subsequent calls to G_set_cat()
- **********************************************************************
- *
- * G_unmark_raster_cats (pcats)
- * struct Categories *pcats structure to hold category info
- *
- * initialize cats.marks: the statistics of how many values of map
- * have each label
- *
- **********************************************************************
- *
- * G_rewind_raster_cats (pcats)
- * struct Categories *pcats structure to hold category info
- *
- * after calll to this function G_get_next_marked_raster_cat() returns
- * rhe first marked cat label.
- *
- **********************************************************************
- *
- * char* G_get_next_marked_raster_cat(pcats, rast1, rast2, stats, data_type)
- * struct Categories *pcats structure to hold category info
- * void *rast1, *rast2; pointers to raster range
- * long *stats;
- * RASTER_MAP_TYPE data_type
- *
- * returns the next marked label.
- * NULL if none found
- *
- **********************************************************************
- *
- * char* G_get_next_marked_f/d/craster_cat(pcats, rast1, rast2, stats)
- * struct Categories *pcats structure to hold category info
- * [D/F]CELL *rast1, *rast2; pointers to raster range
- * long *stats;
- *
- * returns the next marked label.
- * NULL if none found
- *
- **********************************************************************
- *
- * G_mark_raster_cats (rast_row, ncols, pcats, data_type)
- * void *raster_row; raster row to update stats
- * struct Categories *pcats structure to hold category info
- * RASTER_MAP_TYPE data_type;
- * Finds the index of label for each raster cell in a row, and
- * increases pcats->marks[index]
- * Note: if there are no explicit cats: only rules for cats, no
- * marking is done.
- *
- **********************************************************************
- *
- * G_mark_c/d/f_raster_cats (rast_row, ncols, pcats)
- * int ncols;
- * [D?F]CELL *raster_row; raster row to update stats
- * struct Categories *pcats structure to hold category info
- *
- * Finds the index of label for each raster cell in a row, and
- * increases pcats->marks[index]
- *
- **********************************************************************
- *
- * G_init_raster_cats (title, pcats)
- * const char *title cell title
- * struct Categories *pcats structure to hold category info
- *
- * Initializes the cats structure for subsequent calls to G_set_cat()
- *
- **********************************************************************
- *
- * G_set_[raster]_cats_fmt (fmt, m1, a1, m2, a2, pcats)
- * const char *fmt user form of the equation format
- * float m1,a1,m2,a2 coefficients
- * struct Categories *pcats structure to hold category info
- *
- * configures the cats structure for the equation. Must be called
- * after G_init_cats().
- *
- **********************************************************************
- *
- * G_set_[raster]_cats_title (title, pcats)
- * const char *title cell file title
- * struct Categories *pcats structure holding category info
- *
- * Store title as cell file in cats structure
- * Returns nothing.
- *
- **********************************************************************
- *
- * G_set_cat (num, label, pcats)
- * CELL num category number
- * const char *label category label
- * struct Categories *pcats structure to hold category info
- *
- * Adds the string buff to represent category "num" in category structure
- * pcats.
- *
- * Returns: 0 is cat is null value -1 too many cats, 1 ok.
- *
- **********************************************************************
- *
- * G_set_[f/d/c]_raster_cat (&val1, &val2, label, pcats)
- * [D/F]CELL *val1, *val2; pointers to raster values
- * const char *label category label
- * struct Categories *pcats structure to hold category info
- *
- * Adds the label for range val1 through val2 in category structure
- * pcats.
- *
- * Returns: 0 if cat is null value -1 too many cats, 1 ok.
- *
- **********************************************************************
- *
- * G_set_raster_cat (val1, val2, label, pcats, data_type)
- * void *val1, *val2; pointers to raster values
- * const char *label category label
- * struct Categories *pcats structure to hold category info
- * RASTER_MAP_TYPE data_type type of raster cell
- *
- * Adds the label for range val1 through val2 in category structure
- * pcats.
- *
- * Returns: 0 if cat is null value -1 too many cats, 1 ok.
- *
- **********************************************************************
- *
- * G_write_[raster]_cats (name, pcats)
- * const char *name name of cell file
- * struct Categories *pcats structure holding category info
- *
- * Writes the category information associated with cell file "name"
- * into current mapset from the structure "pcats".
- *
- * returns: 1 if successful
- * -1 on fail
- **********************************************************************
- *
- * G_write_vector_cats (name, pcats)
- * const char *name name of vector map
- * struct Categories *pcats structure holding category info
- *
- * Writes the category information associated with vector map "name"
- * into current mapset from the structure "pcats".
- *
- * returns: 1 if successful
- * -1 on fail
- **********************************************************************
- *
- * G_free_[raster]_cats (pcats)
- * struct Categories *pcats structure holding category info
- *
- * Releases memory allocated for the cats structure
- **********************************************************************/
- #include <stdlib.h>
- #include <string.h>
- #include <grass/gis.h>
- #include <grass/glocale.h>
- static void get_cond(char **, char *, DCELL);
- static int get_fmt(char **, char *, int *);
- static int cmp(const void *, const void *);
- static int write_cats(const char *element, const char *name, struct Categories *cats);
- static CELL read_cats(const char *element,
- const char *name,
- const char *mapset, struct Categories * pcats, int full);
- /*!
- * \brief read raster category file
- *
- * The category file for raster map
- * <b>name</b> in <b>mapset</b> is read into the <b>cats</b> structure. If
- * there is an error reading the category file, a diagnostic message is printed
- * and -1 is returned. Otherwise, 0 is returned.
- *
- * \param name
- * \param mapset
- * \param cats
- * \return int
- */
- int G_read_cats(const char *name,
- const char *mapset, struct Categories *pcats)
- {
- return G_read_raster_cats(name, mapset, pcats);
- }
- /*!
- * \brief
- *
- * Is the same as existing G_read_cats()
- *
- * \param name
- * \param mapset
- * \param pcats
- * \return int
- */
- int G_read_raster_cats(const char *name,
- const char *mapset, struct Categories *pcats)
- {
- char *type;
- switch (read_cats("cats", name, mapset, pcats, 1)) {
- case -2:
- type = "missing";
- break;
- case -1:
- type = "invalid";
- break;
- default:
- return 0;
- }
- G_warning(_("category support for [%s] in mapset [%s] %s"),
- name, mapset, type);
- return -1;
- }
- /*!
- * \brief read vector category file
- *
- * The category file for vector map
- * <b>name</b> in <b>mapset</b> is read into the <b>cats</b> structure. If
- * there is an error reading the category file, a diagnostic message is printed
- * and -1 is returned. Otherwise, 0 is returned.
- *
- * \param name
- * \param mapset
- * \param cats
- * \return int
- */
- int G_read_vector_cats(const char *name,
- const char *mapset, struct Categories *pcats)
- {
- char *type;
- switch (read_cats("dig_cats", name, mapset, pcats, 1)) {
- case -2:
- type = "missing";
- break;
- case -1:
- type = "invalid";
- break;
- default:
- return 0;
- }
- G_warning(_("category support for vector map [%s] in mapset [%s] %s"),
- name, mapset, type);
- return -1;
- }
- CELL G_number_of_cats(const char *name, const char *mapset)
- {
- struct Range range;
- CELL min, max;
- /* return the max category number */
- if (G_read_range(name, mapset, &range) < 0)
- return -1;
- G_get_range_min_max(&range, &min, &max);
- if (G_is_c_null_value(&max))
- max = 0;
- return max;
- }
- static CELL read_cats(const char *element,
- const char *name,
- const char *mapset, struct Categories * pcats, int full)
- {
- FILE *fd;
- char buff[1024];
- CELL cat;
- DCELL val1, val2;
- int old = 0, fp_map;
- long num = -1;
- if (strncmp(element, "dig", 3) == 0)
- fp_map = 0;
- else
- fp_map = G_raster_map_is_fp(name, mapset);
- if (!(fd = G_fopen_old(element, name, mapset)))
- return -2;
- /* Read the number of categories */
- if (G_getl(buff, sizeof buff, fd) == 0)
- goto error;
- if (sscanf(buff, "# %ld", &num) == 1)
- old = 0;
- else if (sscanf(buff, "%ld", &num) == 1)
- old = 1;
- if (!full) {
- fclose(fd);
- if (num < 0)
- return 0; /* coorect */
- return (CELL) num;
- }
- /* Read the title for the file */
- if (G_getl(buff, sizeof buff, fd) == 0)
- goto error;
- G_strip(buff);
- /* G_ascii_check(buff) ; */
- G_init_raster_cats(buff, pcats);
- if (num >= 0)
- pcats->num = num;
- if (!old) {
- char fmt[256];
- float m1, a1, m2, a2;
- if (G_getl(fmt, sizeof fmt, fd) == 0)
- goto error;
- /* next line contains equation coefficients */
- if (G_getl(buff, sizeof buff, fd) == 0)
- goto error;
- if (sscanf(buff, "%f %f %f %f", &m1, &a1, &m2, &a2) != 4)
- goto error;
- G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
- }
- /* Read all category names */
- for (cat = 0;; cat++) {
- char label[1024];
- if (G_getl(buff, sizeof buff, fd) == 0)
- break;
- if (old)
- G_set_cat(cat, buff, pcats);
- else {
- *label = 0;
- if (sscanf(buff, "%1s", label) != 1)
- continue;
- if (*label == '#')
- continue;
- *label = 0;
- /* for fp maps try to read a range of data */
- if (fp_map
- && sscanf(buff, "%lf:%lf:%[^\n]", &val1, &val2, label) == 3)
- G_set_raster_cat(&val1, &val2, label, pcats, DCELL_TYPE);
- else if (sscanf(buff, "%d:%[^\n]", &cat, label) >= 1)
- G_set_raster_cat(&cat, &cat, label, pcats, CELL_TYPE);
- else if (sscanf(buff, "%lf:%[^\n]", &val1, label) >= 1)
- G_set_raster_cat(&val1, &val1, label, pcats, DCELL_TYPE);
- else
- goto error;
- }
- }
- fclose(fd);
- return 0;
- error:
- fclose(fd);
- return -1;
- }
- /*!
- * \brief get title from category structure struct
- *
- * Map layers store a one-line title in the category structure
- * as well. This routine returns a pointer to the title contained in the
- * <b>cats</b> structure. A legal pointer is always returned. If the map
- * layer does not have a title, then a pointer to the empty string "" is
- * returned.
- *
- * \param cats
- * \return char *
- */
- char *G_get_cats_title(const struct Categories *pcats)
- {
- return G_get_raster_cats_title(pcats);
- }
- /*!
- * \brief get raster cats title
- *
- * Returns pointer to a string with title.
- *
- * \param pcats
- * \return char *
- */
- char *G_get_raster_cats_title(const struct Categories *pcats)
- {
- return pcats->title ? pcats->title : "";
- }
- /*!
- * \brief get a category label
- *
- * This routine looks up category <b>n</b> in the <b>cats</b>
- * structure and returns a pointer to a string which is the label for the
- * category. A legal pointer is always returned. If the category does not exist
- * in <b>cats,</b> then a pointer to the empty string "" is returned.
- * <b>Warning.</b> The pointer that is returned points to a hidden static
- * buffer. Successive calls to G_get_cat( ) overwrite this buffer.
- *
- * \param n
- * \param cats
- * \return char *
- */
- char *G_get_cat(CELL num, struct Categories *pcats)
- {
- return G_get_c_raster_cat(&num, pcats);
- }
- /*!
- * \brief
- *
- * given a CELL value <em>val</em> Returns pointer to a string describing
- * category.
- *
- * \param val
- * \param pcats
- * \return char *
- */
- char *G_get_c_raster_cat(CELL * rast, struct Categories *pcats)
- {
- return G_get_raster_cat(rast, pcats, CELL_TYPE);
- }
- /*!
- * \brief
- *
- * given a FCELL value <em>val</em> Returns pointer to a string
- * describing category.
- *
- * \param val
- * \param pcats
- * \return char *
- */
- char *G_get_f_raster_cat(FCELL * rast, struct Categories *pcats)
- {
- return G_get_raster_cat(rast, pcats, FCELL_TYPE);
- }
- /*!
- * \brief
- *
- * given a DCELL value <em>val</em> Returns pointer to a string
- * describing category.
- *
- * \param val
- * \param pcats
- * \return char *
- */
- char *G_get_d_raster_cat(DCELL * rast, struct Categories *pcats)
- {
- return G_get_raster_cat(rast, pcats, DCELL_TYPE);
- }
- /*!
- * \brief
- *
- * given a raster value <em>val</em> of type <em>data_type</em> Returns pointer to a string
- * describing category.
- *
- * \param val
- * \param pcats
- * \param data_type
- * \return char *
- */
- char *G_get_raster_cat(void *rast,
- struct Categories *pcats, RASTER_MAP_TYPE data_type)
- {
- static char label[1024];
- char *f, *l, *v;
- CELL i;
- DCELL val;
- float a[2];
- char fmt[30], value_str[30];
- if (G_is_null_value(rast, data_type)) {
- sprintf(label, "no data");
- return label;
- }
- /* first search the list of labels */
- *label = 0;
- val = G_get_raster_value_d(rast, data_type);
- i = G_quant_get_cell_value(&pcats->q, val);
- /* DEBUG fprintf (stderr, "val %lf found i %d\n", val, i); */
- if (!G_is_c_null_value(&i) && i < pcats->ncats) {
- if (pcats->labels[i] != NULL)
- return pcats->labels[i];
- return label;
- }
- /* generate the label */
- if ((f = pcats->fmt) == NULL)
- return label;
- a[0] = (float)val *pcats->m1 + pcats->a1;
- a[1] = (float)val *pcats->m2 + pcats->a2;
- l = label;
- while (*f) {
- if (*f == '$') {
- f++;
- if (*f == '$')
- *l++ = *f++;
- else if (*f == '?') {
- f++;
- get_cond(&f, v = value_str, val);
- while (*v)
- *l++ = *v++;
- }
- else if (get_fmt(&f, fmt, &i)) {
- sprintf(v = value_str, fmt, a[i]);
- while (*v)
- *l++ = *v++;
- }
- else
- *l++ = '$';
- }
- else {
- *l++ = *f++;
- }
- }
- *l = 0;
- return label;
- }
- /*!
- * \brief
- *
- * Sets marks
- * for all categories to 0. This initializes Categories structure for subsequest
- * calls to G_mark_raster_cats (rast_row,...) for each row of data, where
- * non-zero mark for i-th label means that some of the cells in rast_row are
- * labeled with i-th label and fall into i-th data range.
- * These marks help determine from the Categories structure which labels were
- * used and which weren't.
- *
- * \param pcats
- * \return
- */
- void G_unmark_raster_cats(struct Categories *pcats)
- { /* structure to hold category info */
- int i;
- for (i = 0; i < pcats->ncats; i++)
- pcats->marks[i] = 0;
- }
- /*!
- * \brief
- *
- * Looks up the category label for each raster value in
- * the <em>rast_row</em> and updates the marks for labels found.
- * NOTE: non-zero mark for i-th label stores the number of of raster cells read
- * so far which are labeled with i-th label and fall into i-th data range.
- *
- * \param rast_row
- * \param ncols
- * \param pcats
- * \return
- */
- void G_mark_c_raster_cats(const CELL * rast_row, /* raster row to update stats */
- int ncols, struct Categories *pcats)
- { /* structure to hold category info */
- G_mark_raster_cats(rast_row, ncols, pcats, CELL_TYPE);
- }
- /*!
- * \brief
- *
- * Looks up the category label for each raster value in
- * the <em>rast_row</em> and updates the marks for labels found.
- * NOTE: non-zero mark for i-th label stores the number of of raster cells read
- * so far which are labeled with i-th label and fall into i-th data range.
- *
- * \param rast_row
- * \param ncols
- * \param pcats
- * \return
- */
- void G_mark_f_raster_cats(const FCELL * rast_row, /* raster row to update stats */
- int ncols, struct Categories *pcats)
- { /* structure to hold category info */
- G_mark_raster_cats(rast_row, ncols, pcats, FCELL_TYPE);
- }
- /*!
- * \brief
- *
- * Looks up the category label for each raster value in
- * the <em>rast_row</em> and updates the marks for labels found.
- * NOTE: non-zero mark for i-th label stores the number of of raster cells read
- * so far which are labeled with i-th label and fall into i-th data range.
- *
- * \param rast_row
- * \param ncols
- * \param pcats
- * \return
- */
- void G_mark_d_raster_cats(const DCELL * rast_row, /* raster row to update stats */
- int ncols, struct Categories *pcats)
- { /* structure to hold category info */
- G_mark_raster_cats(rast_row, ncols, pcats, DCELL_TYPE);
- }
- /*!
- * \brief
- *
- * Looks up the category
- * label for each raster value in the <em>rast_row</em> (row of raster cell value)
- * and updates the marks for labels found.
- * NOTE: non-zero mark for i-th label stores the number of of raster cells read
- * so far which are labeled with i-th label and fall into i-th data range.
- *
- * \param rast_row
- * \param ncols
- * \param pcats
- * \param data_type
- * \return int
- */
- int G_mark_raster_cats(const void *rast_row, /* raster row to update stats */
- int ncols, struct Categories *pcats, /* structure to hold category info */
- RASTER_MAP_TYPE data_type)
- {
- CELL i;
- while (ncols-- > 0) {
- i = G_quant_get_cell_value(&pcats->q,
- G_get_raster_value_d(rast_row, data_type));
- if (G_is_c_null_value(&i))
- continue;
- if (i > pcats->ncats)
- return -1;
- pcats->marks[i]++;
- rast_row = G_incr_void_ptr(rast_row, G_raster_size(data_type));
- }
- return 1;
- }
- /*!
- * \brief
- *
- * after call to
- * this function G_get_next_marked_raster_cat() returns the first marked
- * cat label.
- *
- * \param pcats
- * \return
- */
- void G_rewind_raster_cats(struct Categories *pcats)
- {
- pcats->last_marked_rule = -1;
- }
- char *G_get_next_marked_d_raster_cat(struct Categories *pcats, /* structure to hold category info */
- DCELL * rast1, DCELL * rast2, /* pointers to raster range */
- long *count)
- {
- char *descr = NULL;
- int found, i;
- found = 0;
- /* pcats->ncats should be == G_quant_nof_rules(&pcats->q) */
- /* DEBUG
- fprintf (stderr, "last marked %d nrules %d\n", pcats->last_marked_rule, G_quant_nof_rules(&pcats->q));
- */
- for (i = pcats->last_marked_rule + 1; i < G_quant_nof_rules(&pcats->q);
- i++) {
- descr = G_get_ith_d_raster_cat(pcats, i, rast1, rast2);
- /* DEBUG fprintf (stderr, "%d %d\n", i, pcats->marks[i]); */
- if (pcats->marks[i]) {
- found = 1;
- break;
- }
- }
- if (!found)
- return NULL;
- *count = pcats->marks[i];
- pcats->last_marked_rule = i;
- return descr;
- }
- char *G_get_next_marked_c_raster_cat(struct Categories *pcats, /* structure to hold category info */
- CELL * rast1, CELL * rast2, /* pointers to raster range */
- long *count)
- {
- return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
- CELL_TYPE);
- }
- char *G_get_next_marked_f_raster_cat(struct Categories *pcats, /* structure to hold category info */
- FCELL * rast1, FCELL * rast2, /* pointers to raster range */
- long *count)
- {
- return G_get_next_marked_raster_cat(pcats, rast1, rast2, count,
- FCELL_TYPE);
- }
- char *G_get_next_marked_raster_cat(struct Categories *pcats, /* structure to hold category info */
- void *rast1, void *rast2, /* pointers to raster range */
- long *count, RASTER_MAP_TYPE data_type)
- {
- DCELL val1, val2;
- char *lab;
- lab = G_get_next_marked_d_raster_cat(pcats, &val1, &val2, count);
- G_set_raster_value_d(rast1, val1, data_type);
- G_set_raster_value_d(rast2, val2, data_type);
- return lab;
- }
- static int get_fmt(char **f, char *fmt, int *i)
- {
- char *ff;
- ff = *f;
- if (*ff == 0)
- return 0;
- if (*ff == '$') {
- *f = ff + 1;
- return 0;
- }
- switch (*ff++) {
- case '1':
- *i = 0;
- break;
- case '2':
- *i = 1;
- break;
- default:
- return 0;
- }
- *fmt++ = '%';
- *fmt++ = '.';
- if (*ff++ != '.') {
- *f = ff - 1;
- *fmt++ = '0';
- *fmt++ = 'f';
- *fmt = 0;
- return 1;
- }
- *fmt = '0';
- while (*ff >= '0' && *ff <= '9')
- *fmt++ = *ff++;
- *fmt++ = 'f';
- *fmt = 0;
- *f = ff;
- return 1;
- }
- static void get_cond(char **f, char *value, DCELL val)
- {
- char *ff;
- ff = *f;
- if (val == 1.) {
- while (*ff)
- if (*ff++ == '$')
- break;
- }
- while (*ff)
- if (*ff == '$') {
- ff++;
- break;
- }
- else
- *value++ = *ff++;
- if (val != 1.) {
- while (*ff)
- if (*ff++ == '$')
- break;
- }
- *value = 0;
- *f = ff;
- }
- /*!
- * \brief set a category label
- *
- * The <b>label</b> is copied into the <b>cats</b> structure
- * for category <b>n.</b>
- *
- * \param n
- * \param label
- * \param cats
- * \return int
- */
- int G_set_cat(CELL num, const char *label, struct Categories *pcats)
- {
- return G_set_c_raster_cat(&num, &num, label, pcats);
- }
- /*!
- * \brief
- *
- * Adds the label for range <em>rast1</em> through <em>rast2</em> in
- * category structure <em>pcats</em>.
- *
- * \param rast1
- * \param rast2
- * \param pcats
- * \return int
- */
- int G_set_c_raster_cat(const CELL * rast1, const CELL * rast2,
- const char *label, struct Categories *pcats)
- {
- return G_set_raster_cat(rast1, rast2, label, pcats, CELL_TYPE);
- }
- /*!
- * \brief
- *
- * Adds the label for range <em>rast1</em> through <em>rast2</em>
- * in category structure <em>pcats</em>.
- *
- * \param rast1
- * \param rast2
- * \param pcats
- * \return int
- */
- int G_set_f_raster_cat(const FCELL * rast1, const FCELL * rast2,
- const char *label, struct Categories *pcats)
- {
- return G_set_raster_cat(rast1, rast2, label, pcats, FCELL_TYPE);
- }
- /*!
- * \brief
- *
- * Adds the label for range <em>rast1</em> through <em>rast2</em>
- * in category structure <em>pcats</em>.
- *
- * \param rast1
- * \param rast2
- * \param pcats
- * \return int
- */
- int G_set_d_raster_cat(const DCELL * rast1, const DCELL * rast2,
- const char *label, struct Categories *pcats)
- {
- long len;
- DCELL dtmp1, dtmp2;
- int i;
- char *descr;
- /* DEBUG fprintf(stderr,"G_set_d_raster_cat(rast1 = %p,rast2 = %p,label = '%s',pcats = %p)\n",
- rast1,rast2,label,pcats); */
- if (G_is_d_null_value(rast1))
- return 0;
- if (G_is_d_null_value(rast2))
- return 0;
- /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): adding quant rule: %f %f %d %d\n", *rast1, *rast2, pcats->ncats, pcats->ncats); */
- /* the set_cat() functions are used in many places to reset the labels
- for the range (or cat) with existing label. In this case we don't
- want to store both rules with identical range even though the result
- of get_cat() will be correct, since it will use rule added later.
- we don't want to overuse memory and we don't want rules which are
- not used to be writen out in cats file. So we first look if
- the label for this range has been sen, and if it has, overwrite it */
- for (i = 0; i < pcats->ncats; i++) {
- descr = G_get_ith_d_raster_cat(pcats, i, &dtmp1, &dtmp2);
- if ((dtmp1 == *rast1 && dtmp2 == *rast2)
- || (dtmp1 == *rast2 && dtmp2 == *rast1)) {
- if (pcats->labels[i] != NULL)
- G_free(pcats->labels[i]);
- pcats->labels[i] = G_store(label);
- G_newlines_to_spaces(pcats->labels[i]);
- G_strip(pcats->labels[i]);
- return 1;
- }
- }
- /* when rule for this range does not exist */
- /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): New rule: adding %d %p\n", i, pcats->labels); */
- G_quant_add_rule(&pcats->q, *rast1, *rast2, pcats->ncats, pcats->ncats);
- pcats->ncats++;
- if (pcats->nalloc < pcats->ncats) {
- /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): need more space nalloc = %d ncats = %d\n", pcats->nalloc,pcats->ncats); */
- len = (pcats->nalloc + 256) * sizeof(char *);
- /* DEBUG fprintf (stderr, "G_set_d_raster_cat(): allocating %d labels(%d)\n", pcats->nalloc + 256,(int)len); */
- if (len != (int)len) { /* make sure len doesn't overflow int */
- pcats->ncats--;
- return -1;
- }
- /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): pcats->nalloc = %d, pcats->labels = (%p), len = %d\n",pcats->nalloc,pcats->labels,(int)len); */
- if (pcats->nalloc) {
- /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): Realloc-ing pcats->labels (%p)\n",pcats->labels); */
- pcats->labels =
- (char **)G_realloc((char *)pcats->labels, (int)len);
- }
- else {
- /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): alloc-ing new labels pointer array\n"); */
- pcats->labels = (char **)G_malloc((int)len);
- }
- /* fflush(stderr); */
- /* DEBUG fprintf (stderr, "G_set_d_raster_cats(): allocating %d marks(%d)\n", pcats->nalloc + 256,(int)len); */
- len = (pcats->nalloc + 256) * sizeof(int);
- if (len != (int)len) { /* make sure len doesn't overflow int */
- pcats->ncats--;
- return -1;
- }
- if (pcats->nalloc)
- pcats->marks = (int *)G_realloc((char *)pcats->marks, (int)len);
- else
- pcats->marks = (int *)G_malloc((int)len);
- pcats->nalloc += 256;
- }
- /* DEBUG fprintf(stderr,"G_set_d_raster_cats(): store new label\n"); */
- pcats->labels[pcats->ncats - 1] = G_store(label);
- G_newlines_to_spaces(pcats->labels[pcats->ncats - 1]);
- G_strip(pcats->labels[pcats->ncats - 1]);
- /* DEBUG
- fprintf (stderr, "%d %s\n", pcats->ncats - 1, pcats->labels[pcats->ncats - 1]);
- */
- /* updates cats.num = max cat values. This is really just used in old
- raster programs, and I am doing it for backwards cmpatibility (Olga) */
- if ((CELL) * rast1 > pcats->num)
- pcats->num = (CELL) * rast1;
- if ((CELL) * rast2 > pcats->num)
- pcats->num = (CELL) * rast2;
- /* DEBUG fprintf(stderr,"G_set_d_raster_cat(): done\n"); */
- /* DEBUG fflush(stderr); */
- return 1;
- }
- /*!
- * \brief
- *
- * Adds the label for range <em>rast1</em> through <em>rast2</em> in category structure <em>pcats</em>.
- *
- * \param rast1
- * \param rast2
- * \param pcats
- * \param data_type
- * \return int
- */
- int G_set_raster_cat(const void *rast1, const void *rast2,
- const char *label,
- struct Categories *pcats, RASTER_MAP_TYPE data_type)
- {
- DCELL val1, val2;
- val1 = G_get_raster_value_d(rast1, data_type);
- val2 = G_get_raster_value_d(rast2, data_type);
- return G_set_d_raster_cat(&val1, &val2, label, pcats);
- }
- /*!
- * \brief write raster category file
- *
- * Writes the category file for the raster map <b>name</b> in
- * the current mapset from the <b>cats</b> structure.
- * Returns 1 if successful. Otherwise, -1 is returned (no diagnostic is
- * printed).
- *
- * \param name
- * \param cats
- * \return int
- */
- int G_write_cats(const char *name, struct Categories *cats)
- {
- return write_cats("cats", name, cats);
- }
- /*!
- * \brief
- *
- * Same as existing G_write_cats()
- *
- * \param name
- * \param pcats
- * \return int
- */
- int G_write_raster_cats(const char *name, struct Categories *cats)
- {
- return write_cats("cats", name, cats);
- }
- /*!
- * \brief write
- * vector category file
- *
- * Writes the category file for the vector map
- * <b>name</b> in the current mapset from the <b>cats</b> structure.
- * Returns 1 if successful. Otherwise, -1 is returned (no diagnostic is
- * printed).
- *
- * \param name
- * \param cats
- * \return int
- */
- int G_write_vector_cats(const char *name, struct Categories *cats)
- {
- return write_cats("dig_cats", name, cats);
- }
- static int write_cats(const char *element, const char *name, struct Categories *cats)
- {
- FILE *fd;
- int i, fp_map;
- char *descr;
- DCELL val1, val2;
- char str1[100], str2[100];
- if (!(fd = G_fopen_new(element, name)))
- return -1;
- /* write # cats - note # indicate 3.0 or later */
- fprintf(fd, "# %ld categories\n", (long)cats->num);
- /* title */
- fprintf(fd, "%s\n", cats->title != NULL ? cats->title : "");
- /* write format and coefficients */
- fprintf(fd, "%s\n", cats->fmt != NULL ? cats->fmt : "");
- fprintf(fd, "%.2f %.2f %.2f %.2f\n",
- cats->m1, cats->a1, cats->m2, cats->a2);
- /* if the map is integer or if this is a vector map, sort labels */
- if (strncmp(element, "dig", 3) == 0)
- fp_map = 0;
- else
- fp_map = G_raster_map_is_fp(name, G_mapset());
- if (!fp_map)
- G_sort_cats(cats);
- /* write the cat numbers:label */
- for (i = 0; i < G_quant_nof_rules(&cats->q); i++) {
- descr = G_get_ith_d_raster_cat(cats, i, &val1, &val2);
- if ((cats->fmt && cats->fmt[0])
- || (descr && descr[0])) {
- if (val1 == val2) {
- sprintf(str1, "%.10f", val1);
- G_trim_decimal(str1);
- fprintf(fd, "%s:%s\n", str1, descr != NULL ? descr : "");
- }
- else {
- sprintf(str1, "%.10f", val1);
- G_trim_decimal(str1);
- sprintf(str2, "%.10f", val2);
- G_trim_decimal(str2);
- fprintf(fd, "%s:%s:%s\n", str1, str2,
- descr != NULL ? descr : "");
- }
- }
- }
- fclose(fd);
- return (1);
- }
- /*!
- * \brief
- *
- * Returns i-th description and i-th data range
- * from the list of category descriptions with corresponding data ranges. end
- * points of data interval in <em>rast1</em> and <em>rast2</em>.
- *
- * \param pcats
- * \param i
- * \param rast1
- * \param rast2
- * \return char *
- */
- char *G_get_ith_d_raster_cat(const struct Categories *pcats,
- int i, DCELL * rast1, DCELL * rast2)
- {
- int index;
- if (i > pcats->ncats) {
- G_set_d_null_value(rast1, 1);
- G_set_d_null_value(rast2, 1);
- return "";
- }
- G_quant_get_ith_rule(&pcats->q, i, rast1, rast2, &index, &index);
- return pcats->labels[index];
- }
- /*!
- * \brief
- *
- * Returns i-th description and i-th data range
- * from the list of category descriptions with corresponding data ranges. end
- * points of data interval in <em>rast1</em> and <em>rast2</em>.
- *
- * \param pcats
- * \param i
- * \param rast1
- * \param rast2
- * \return char *
- */
- char *G_get_ith_f_raster_cat(const struct Categories *pcats,
- int i, void *rast1, void *rast2)
- {
- RASTER_MAP_TYPE data_type = FCELL_TYPE;
- char *tmp;
- DCELL val1, val2;
- tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
- G_set_raster_value_d(rast1, val1, data_type);
- G_set_raster_value_d(rast2, val2, data_type);
- return tmp;
- }
- /*!
- * \brief
- *
- * Returns i-th description and i-th data range
- * from the list of category descriptions with corresponding data ranges. end
- * points of data interval in <em>rast1</em> and <em>rast2</em>.
- *
- * \param pcats
- * \param i
- * \param rast1
- * \param rast2
- * \return char *
- */
- char *G_get_ith_c_raster_cat(const struct Categories *pcats,
- int i, void *rast1, void *rast2)
- {
- RASTER_MAP_TYPE data_type = CELL_TYPE;
- char *tmp;
- DCELL val1, val2;
- tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
- G_set_raster_value_d(rast1, val1, data_type);
- G_set_raster_value_d(rast2, val2, data_type);
- return tmp;
- }
- /*!
- * \brief
- *
- * Returns i-th
- * description and i-th data range from the list of category descriptions with
- * corresponding data ranges. Stores end points of data interval in <em>rast1</em>
- * and <em>rast2</em> (after converting them to <em>data_type</em>.
- *
- * \param pcats
- * \param i
- * \param rast1
- * \param rast2
- * \param data_type
- * \return char *
- */
- char *G_get_ith_raster_cat(const struct Categories *pcats, int i, void *rast1,
- void *rast2, RASTER_MAP_TYPE data_type)
- {
- char *tmp;
- DCELL val1, val2;
- tmp = G_get_ith_d_raster_cat(pcats, i, &val1, &val2);
- G_set_raster_value_d(rast1, val1, data_type);
- G_set_raster_value_d(rast2, val2, data_type);
- return tmp;
- }
- /*!
- * \brief initialize category structure
- *
- * To construct a new category file, the
- * structure must first be initialized. This routine initializes the
- * <b>cats</b> structure, and copies the <b>title</b> into the structure.
- * The number of categories is set initially to <b>n.</b>
- * For example:
- \code
- struct Categories cats;
- G_init_cats ( (CELL)0, "", &cats);
- \endcode
- *
- * \param n
- * \param title
- * \param cats
- */
- void G_init_cats(CELL num, const char *title, struct Categories *pcats)
- {
- G_init_raster_cats(title, pcats);
- pcats->num = num;
- }
- /*!
- * \brief
- *
- * Same as existing G_init_raster_cats() only ncats argument is
- * missign. ncats has no meaning in new Categories structure and only stores
- * (int) largets data value for backwards compatibility.
- *
- * \param title
- * \param pcats
- * \return
- */
- void G_init_raster_cats(const char *title, struct Categories *pcats)
- {
- G_set_raster_cats_title(title, pcats);
- pcats->labels = NULL;
- pcats->nalloc = 0;
- pcats->ncats = 0;
- pcats->num = 0;
- pcats->fmt = NULL;
- pcats->m1 = 0.0;
- pcats->a1 = 0.0;
- pcats->m2 = 0.0;
- pcats->a2 = 0.0;
- pcats->last_marked_rule = -1;
- G_quant_init(&pcats->q);
- }
- /*!
- * \brief set title in category structure
- *
- * The <b>title</b> is copied into the
- * <b>cats</b> structure.
- *
- * \param title
- * \param cats
- * \return
- */
- void G_set_cats_title(const char *title, struct Categories *pcats)
- {
- G_set_raster_cats_title(title, pcats);
- }
- /*!
- * \brief
- *
- * Same as existing G_set_cats_title()
- *
- * \param title
- * \param pcats
- * \return
- */
- void G_set_raster_cats_title(const char *title, struct Categories *pcats)
- {
- if (title == NULL)
- title = "";
- pcats->title = G_store(title);
- G_newlines_to_spaces(pcats->title);
- G_strip(pcats->title);
- }
- void G_set_cats_fmt(const char *fmt, double m1, double a1, double m2,
- double a2, struct Categories *pcats)
- {
- G_set_raster_cats_fmt(fmt, m1, a1, m2, a2, pcats);
- }
- /*!
- * \brief
- *
- * Same as existing G_set_cats_fmt()
- *
- * \param fmt
- * \param m1
- * \param a1
- * \param m2
- * \param a2
- * \param pcats
- */
- void G_set_raster_cats_fmt(const char *fmt, double m1, double a1, double m2,
- double a2, struct Categories *pcats)
- {
- pcats->m1 = m1;
- pcats->a1 = a1;
- pcats->m2 = m2;
- pcats->a2 = a2;
- pcats->fmt = G_store(fmt);
- G_newlines_to_spaces(pcats->fmt);
- G_strip(pcats->fmt);
- }
- /*!
- * \brief free category structure memory
- *
- * Frees memory allocated by<i>G_read_cats, G_init_cats</i>
- * and<i>G_set_cat.</i>
- *
- * \param cats
- * \return
- */
- void G_free_cats(struct Categories *pcats)
- {
- G_free_raster_cats(pcats);
- }
- /*!
- * \brief
- *
- * Same as existing G_free_cats()
- *
- * \param pcats
- * \return
- */
- void G_free_raster_cats(struct Categories *pcats)
- {
- int i;
- if (pcats->title != NULL) {
- G_free(pcats->title);
- pcats->title = NULL;
- }
- if (pcats->fmt != NULL) {
- G_free(pcats->fmt);
- pcats->fmt = NULL;
- }
- if (pcats->ncats > 0) {
- for (i = 0; i < pcats->ncats; i++)
- if (pcats->labels[i] != NULL)
- G_free(pcats->labels[i]);
- G_free(pcats->labels);
- G_free(pcats->marks);
- pcats->labels = NULL;
- }
- G_quant_free(&pcats->q);
- pcats->ncats = 0;
- pcats->nalloc = 0;
- }
- /*!
- * \brief
- *
- * Allocates NEW space for quant rules and labels n
- * <em>pcats_to</em> and copies all info from <em>pcats_from</em> cats to <em>pcats_to</em> cats.
- * returns:
- * 0 if successful
- * -1 on fail
- *
- * \param pcats_to
- * \param pcats_from
- * \return
- */
- void G_copy_raster_cats(struct Categories *pcats_to,
- const struct Categories *pcats_from)
- {
- int i;
- char *descr;
- DCELL d1, d2;
- G_init_raster_cats(pcats_from->title, pcats_to);
- for (i = 0; i < pcats_from->ncats; i++) {
- descr = G_get_ith_d_raster_cat(pcats_from, i, &d1, &d2);
- G_set_d_raster_cat(&d1, &d2, descr, pcats_to);
- }
- }
- int G_number_of_raster_cats(struct Categories *pcats)
- {
- return pcats->ncats;
- }
- static struct Categories save_cats;
- int G_sort_cats(struct Categories *pcats)
- {
- int *indexes, i, ncats;
- char *descr;
- DCELL d1, d2;
- if (pcats->ncats <= 1)
- return -1;
- ncats = pcats->ncats;
- /* DEBUG fprintf(stderr,"G_sort_cats(): Copying to save cats buffer\n"); */
- G_copy_raster_cats(&save_cats, pcats);
- G_free_raster_cats(pcats);
- indexes = (int *)G_malloc(sizeof(int) * ncats);
- for (i = 0; i < ncats; i++)
- indexes[i] = i;
- qsort(indexes, ncats, sizeof(int), cmp);
- G_init_raster_cats(save_cats.title, pcats);
- for (i = 0; i < ncats; i++) {
- descr = G_get_ith_d_raster_cat(&save_cats, indexes[i], &d1, &d2);
- /* DEBUG fprintf(stderr,"G_sort_cats(): Write sorted cats, pcats = %p pcats->labels = %p\n",pcats,pcats->labels); */
- G_set_d_raster_cat(&d1, &d2, descr, pcats);
- /* DEBUG fflush(stderr); */
- }
- G_free_raster_cats(&save_cats);
- /* DEBUG fprintf(stderr,"G_sort_cats(): Done\n"); */
- /* fflush(stderr); */
- return 0;
- }
- static int cmp(const void *aa, const void *bb)
- {
- const int *a = aa, *b = bb;
- DCELL min_rast1, min_rast2, max_rast1, max_rast2;
- CELL index;
- G_quant_get_ith_rule(&(save_cats.q), *a,
- &min_rast1, &max_rast1, &index, &index);
- G_quant_get_ith_rule(&(save_cats.q), *b,
- &min_rast2, &max_rast2, &index, &index);
- if (min_rast1 < min_rast2)
- return -1;
- if (min_rast1 > min_rast2)
- return 1;
- return 0;
- }
|