diff --git a/doc/rst/source/grd2cpt.rst b/doc/rst/source/grd2cpt.rst index bee982ebba6..6f6d86a5d02 100644 --- a/doc/rst/source/grd2cpt.rst +++ b/doc/rst/source/grd2cpt.rst @@ -17,7 +17,7 @@ Synopsis [ |-C|\ *cpt* ] [ |-D|\ [**i**\|\ **o**] ] [ |-E|\ [*nlevels*][**+c**][**+f**\ *file*] ] -[ |-F|\ [**R**\|\ **r**\|\ **h**\|\ **c**][**+c**] ] +[ |-F|\ [**R**\|\ **r**\|\ **h**\|\ **c**][**+c**\ [*label*]] ] [ |-G|\ *zlo*\ /\ *zhi* ] [ |-H| ] [ |-I|\ [**c**][**z**] ] @@ -120,11 +120,17 @@ Optional Arguments .. _-F: -**-F**\ [**R**\|\ **r**\|\ **h**\|\ **c**][**+c**] +**-F**\ [**R**\|\ **r**\|\ **h**\|\ **c**][**+c**\ [*label*]] Force output CPT to written with r/g/b codes, gray-scale values or color name (**R**, default) or r/g/b codes only (**r**), or h-s-v codes (**h**), or c/m/y/k codes (**c**). Optionally or alternatively, append **+c** to write discrete palettes in categorical format. + If *label* is appended then we create labels for each category to be used + when the CPT is plotted. The *label* may be a comma-separated list of + category names (you can skip a category by not giving a name), or give + *start*[-], where we automatically build monotonically increasing labels + from *start* (a single letter or an integer). Append - to build ranges + *start*-*start+1* instead. .. _-G: diff --git a/doc/rst/source/makecpt.rst b/doc/rst/source/makecpt.rst index 8d3d284a54c..e2db8143803 100644 --- a/doc/rst/source/makecpt.rst +++ b/doc/rst/source/makecpt.rst @@ -17,7 +17,7 @@ Synopsis [ |-C|\ *cpt* ] [ |-D|\ [**i**\|\ **o**] ] [ |-E|\ [*nlevels*] ] -[ |-F|\ [**R**\|\ **r**\|\ **h**\|\ **c**][**+c**]] +[ |-F|\ [**R**\|\ **r**\|\ **h**\|\ **c**][**+c**\ [*label*]]] [ |-G|\ *zlo*\ /\ *zhi* ] [ |-H| ] [ |-I|\ [**c**][**z**] ] @@ -111,11 +111,17 @@ Optional Arguments .. _-F: -**-F**\ [**R**\|\ **r**\|\ **h**\|\ **c**][**+c**]] +**-F**\ [**R**\|\ **r**\|\ **h**\|\ **c**][**+c**\ [*label*]] Force output CPT to be written with r/g/b codes, gray-scale values or color name (**R**, default) or r/g/b codes only (**r**), or h-s-v codes (**h**), or c/m/y/k codes (**c**). Optionally or alternatively, append **+c** to write discrete palettes in categorical format. + If *label* is appended then we create labels for each category to be used + when the CPT is plotted. The *label* may be a comma-separated list of + category names (you can skip a category by not giving a name), or give + *start*[-], where we automatically build monotonically increasing labels + from *start* (a single letter or an integer). Append - to build ranges + *start*-*start+1* instead. .. _-G: @@ -313,6 +319,15 @@ we always get a color regardless of the *z* value, try gmt makecpt -Cjet -T0/500 -Ww > wrapped.cpt +To build a categorical table with 3 categories and add specific category +names to them, try:: + + gmt makecpt -Ccubhelix -T0/3/1 -F+cClouds,Trees,Water > cat.cpt + +To instead add unique category labels A, B, C, ... to a 10-item categorical CPT, try:: + + gmt makecpt -Cjet -T0/q0/1 -F+cA + .. include:: cpt_notes.rst_ Bugs diff --git a/src/gmt_prototypes.h b/src/gmt_prototypes.h index 2d8fc3a1114..fc8b771701a 100644 --- a/src/gmt_prototypes.h +++ b/src/gmt_prototypes.h @@ -370,6 +370,7 @@ EXTERN_MSC bool gmt_this_alloc_level (struct GMT_CTRL *GMT, unsigned int alloc_l /* gmt_support.c: */ +EXTERN_MSC char ** gmt_cat_cpt_labels (struct GMT_CTRL *GMT, char *label, unsigned int n); EXTERN_MSC bool gmt_same_fill (struct GMT_CTRL *GMT, struct GMT_FILL *F1, struct GMT_FILL *F2); EXTERN_MSC unsigned int gmt_contour_first_pos (struct GMT_CTRL *GMT, char *arg); EXTERN_MSC unsigned int gmt_contour_A_arg_parsing (struct GMT_CTRL *GMT, char *arg, struct CONTOUR_ARGS *A); diff --git a/src/gmt_support.c b/src/gmt_support.c index 121b230847f..712f0b29539 100644 --- a/src/gmt_support.c +++ b/src/gmt_support.c @@ -7407,6 +7407,55 @@ unsigned int gmt_validate_cpt_parameters (struct GMT_CTRL *GMT, struct GMT_PALET return GMT_NOERROR; } +char ** gmt_cat_cpt_labels (struct GMT_CTRL *GMT, char *label, unsigned int n) { + /* Generate categorical labels for n categories from the label magic argument */ + unsigned int k = 0; + char **Clabel = gmt_M_memory (GMT, NULL, n, char *); + + if (strchr (label, ',')) { /* Got list of category names */ + char *word = NULL, *trail = NULL, *orig = strdup (label); + trail = orig; + while ((word = strsep (&trail, ",")) != NULL && k < n) { + if (*word != '\0') /* Skip empty strings */ + Clabel[k] = strdup (word); + k++; + } + gmt_M_str_free (orig); + } + else { /* Auto-build the labels */ + unsigned int mode; + int start; + char string[GMT_LEN64] = {""}; + if (isdigit (label[0])) { /* Integer categories */ + mode = 1; + start = atoi (label); + } + else { /* Letter categories */ + mode = 3; + start = label[0]; + } + if (label[strlen(label)-1] == '-') mode++; /* Wants a range */ + for (k = 0; k < n; k++) { + switch (mode) { + case 1: /* Single integer label */ + sprintf (string, "%d", start+k); + break; + case 2: /* Integer range label */ + sprintf (string, "%d-%d", start+k, start+k+1); + break; + case 3: /* Single letter label */ + sprintf (string, "%c", start+k); + break; + case 4: /* Character range label */ + sprintf (string, "%c-%c", start+k, start+k+1); + break; + } + Clabel[k] = strdup (string); + } + } + return Clabel; +} + /*! . */ struct GMT_PALETTE * gmtlib_read_cpt (struct GMT_CTRL *GMT, void *source, unsigned int source_type, unsigned int cpt_flags) { /* Opens and reads a color palette file in RGB, HSV, or CMYK of arbitrary length. diff --git a/src/grd2cpt.c b/src/grd2cpt.c index 36f08120596..e2f42fbd8de 100644 --- a/src/grd2cpt.c +++ b/src/grd2cpt.c @@ -71,10 +71,11 @@ struct GRD2CPT_CTRL { char *file; unsigned int levels; } E; - struct GRD2CPT_F { /* -F[r|R|h|c][+c] */ + struct GRD2CPT_F { /* -F[r|R|h|c][+c[