Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion doc/rst/source/explain_-B.rst_
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ The Axes settings are specified by

but you may also split this into two separate invocations for clarity, i.e.,

| **-B**\ [**p**\|\ **s**][**x**\|\ **y**\|\ **z**][**+a**\ *angle*\|\ **n**\|\ **p**][**+f**]\
| **-B**\ [**p**\|\ **s**][**x**\|\ **y**\|\ **z**][**+a**\ *angle*\|\ **n**\|\ **p**][**+e**\ [**l**\|\ **u**]][**+f**]\
[**+l**\|\ **L**\ *label*][**+p**\ *prefix*][**+s**\|\ **S**\ *seclabel*][**+u**\ *unit*]
| **-B**\ [**p**\|\ **s**][**x**\|\ **y**\|\ **z**]\ *intervals*

Expand All @@ -110,6 +110,8 @@ The following modifiers can be appended to **-B** to control the Axes settings:
- **x**\|\ **y**\|\ **z** to set which axes the modifiers apply to [default is **xy**]. If you wish to give different
annotation intervals or labels for the various axes then you must repeat the **B** option for each axis. For a
3-D plot with the **-p** and **-Jz** options used, **-Bz** can be used to provide settings for the verical axis.
- **+e** to give skip annotations that fall exactly at the ends of the axis. Append **l** or **u** to only
skip the lower or upper annotation, respectively.
- **+f** (for geographic axes only) to give fancy annotations with W\|\ E\|\ S\|\ N suffices encoding the sign.
- **+l**\|\ **+L**\ *label* (for Cartesian plots only) to add a label to an axis. **+l** uses the default
label orientation; **+L** forces a horizontal label for *y*-axes, which is useful for very short labels.
Expand Down
5 changes: 5 additions & 0 deletions src/gmt_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,11 @@ enum GMT_time_period {
/* Valid options to psconvert from figure and begin */
#define GMT_PSCONVERT_LIST "ACDEHIMNQS"

/* Valid frame setting modifiers */
#define GMT_FRAME_MODIFIERS "bginotwxyz"
/* Valid axis setting modifiers */
#define GMT_AXIS_MODIFIERS "aefLlpsSu"

/* Settings for usage message indents and break/continue characters */

#define GMT_LINE_BREAK "\xe2\x8f\x8e" /* Glyph for return symbol in UTF-8 */
Expand Down
33 changes: 23 additions & 10 deletions src/gmt_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -4367,9 +4367,10 @@ GMT_LOCAL int gmtinit_parse5_B_option (struct GMT_CTRL *GMT, char *in) {
* Axis settings:
* -B[p|s][x|y|z]<info>
* where <info> is of the format
* <intervals>[+a<angle>|n|p][+L|l<label>][+S|s<altlabel>][+p<prefix>][+u<unit>]
* <intervals>[+a<angle>|n|p][+e[l|u]][+L|l<label>][+S|s<altlabel>][+p<prefix>][+u<unit>]
* and each <intervals> is a concatenation of one or more [t][value]
* +a<angle> sets a fixed annotation angle with respect to axis (Cartesian only), n or p for normal or parallel
* +e[l|u] tells GMT to not plot an annotation at the lower and|or upper end of an axis [both are plotted]
* +l<label> as labels for the respective axes [none]. Use +L for only horizontal labels
* +s<altlabel> as alternate label for the far axis [same as <label>]. Use +S for only horizontal labels
* +u<unit> as as annotation suffix unit [none].
Expand Down Expand Up @@ -4404,7 +4405,7 @@ GMT_LOCAL int gmtinit_parse5_B_option (struct GMT_CTRL *GMT, char *in) {
if ((error = gmtinit_parse5_B_frame_setting (GMT, in)) >= 0) return (error); /* Parsed the -B frame settings separately */
error = 0; /* Reset since otherwise it is -1 */

if (gmt_found_modifier (GMT, in, "bginotwxyz")) {
if (gmt_found_modifier (GMT, in, GMT_FRAME_MODIFIERS)) {
GMT_Report (GMT->parent, GMT_MSG_ERROR, "Option -B: Found frame setting modifiers (+b|g|i|n|o|t|w|x|y|z) mixed with axes settings!\n");
return (GMT_PARSE_ERROR);
}
Expand Down Expand Up @@ -4438,9 +4439,9 @@ GMT_LOCAL int gmtinit_parse5_B_option (struct GMT_CTRL *GMT, char *in) {
GMT->current.map.frame.axis[GMT_Z].angle = 0.0; /* Default is plotting normal to axis for Z, i.e., will look horizontal on the plot */
GMT->current.map.frame.axis[GMT_Z].use_angle = true;
strncpy (text, &in[k], GMT_BUFSIZ-1); /* Make a copy of the input, starting after the leading -B[p|s][xyz] indicators */
gmt_handle5_plussign (GMT, text, "afLlpsSu", 0); /* Temporarily change any +<letter> except +L|l, +f, +p, +S|s, +u to ASCII 1 to avoid interference with +modifiers */
k = 0; /* Start at beginning of text and look for first occurrence of +L|l, +f, +p, +S|s or +u */
while (text[k] && !(text[k] == '+' && strchr ("afLlpSsu", text[k+1]))) k++;
gmt_handle5_plussign (GMT, text, GMT_AXIS_MODIFIERS, 0); /* Temporarily change any +<letter> except +L|l, +f, +p, +S|s, +u to ASCII 1 to avoid interference with +modifiers */
k = 0; /* Start at beginning of text and look for first occurrence of +L|l, +e, +f, +p, +S|s or +u */
while (text[k] && !(text[k] == '+' && strchr (GMT_AXIS_MODIFIERS, text[k+1]))) k++;
gmt_M_memset (orig_string, GMT_BUFSIZ, char);
strncpy (orig_string, text, k); /* orig_string now has the interval information */
gmt_handle5_plussign (GMT, orig_string, NULL, 1); /* Recover any non-modifier plus signs */
Expand Down Expand Up @@ -4498,6 +4499,17 @@ GMT_LOCAL int gmtinit_parse5_B_option (struct GMT_CTRL *GMT, char *in) {
else
GMT_Report (GMT->parent, GMT_MSG_WARNING, "Option -B: Cannot use +f for Cartesian axes - modifier ignored\n");
break;
case 'e': /* Turn off end annotations if within distance of axis en */
switch (p[1]) { /* See if lower or upper was specified, or default to both */
case 'l': GMT->current.map.frame.axis[no].skip[0] = true; break;
case 'u': GMT->current.map.frame.axis[no].skip[1] = true; break;
case '\0': GMT->current.map.frame.axis[no].skip[0] = GMT->current.map.frame.axis[no].skip[1] = true; break;
default:
GMT_Report (GMT->parent, GMT_MSG_WARNING, "Option -B: Unrecognized argument to modifier +e (%s). Syntax is +e[l|u].\n", &p[1]);
error++;
break;
}
break;
case 'L': /* Force horizontal axis label */
GMT->current.map.frame.axis[no].label_mode = 1;
/* Intentionally fall through - to 'l' */
Expand Down Expand Up @@ -7138,7 +7150,7 @@ void gmtlib_explain_options (struct GMT_CTRL *GMT, char *options) {
"The full axes specification is");
GMT_Usage (API, 3, "-B[p|s][x|y|z]<intervals>[+a<angle>|n|p][+f][+l|L<label>][+p<prefix>][+s|S<secondary_label>][+u<unit>");
GMT_Usage (API, -2, "Alternatively, you may break this syntax into two separate -B options:");
GMT_Usage (API, 3, "-B[p|s][x|y|z][+a<angle>|n|p][+f][+l|L<label>][+p<prefix>][+s|S<secondary_label>][+u<unit>]");
GMT_Usage (API, 3, "-B[p|s][x|y|z][+a<angle>|n|p][+e[l|u]][+f][+l|L<label>][+p<prefix>][+s|S<secondary_label>][+u<unit>]");
GMT_Usage (API, 3, "-B[p|s][x|y|z]<intervals>");
GMT_Usage (API, -2, "There are two levels of annotations: Primary and secondary (most situations only require primary). "
"The -B[p] sets (p)rimary (more frequent) annotations while -Bs sets (s)econdary (less frequent) annotations. "
Expand Down Expand Up @@ -7182,9 +7194,8 @@ void gmtlib_explain_options (struct GMT_CTRL *GMT, char *options) {
"When <stride> is omitted, a reasonable value will be determined automatically, e.g., -Bafg. "
"Log10 axis: Append l to annotate log10 (value) or p for 10^(log10(value)) [Default annotates value]. "
"Power axis: Append p to annotate value at equidistant pow increments [Default is nonlinear]. Optional modifiers: ");
GMT_Usage (API, 3, "+p Prepend <prefix> to each annotation (e.g., $ 10, $ 20 ...).");
GMT_Usage (API, 3, "+u Append <unit> to each annotation (e.g., 5 km, 10 km ...).");
GMT_Usage (API, 3, "+a Append <angle> for slanted or use +an|p for orthogonal|parallel annotations [+ap].");
GMT_Usage (API, 3, "+e Skip annotation that land exactly at one (append l or u) or both ends of the axis [no skipping].");
GMT_Usage (API, 3, "+f Let geographic axes place \"fancy\" annotations with W|E|S|N suffices.");
GMT_Usage (API, 3, "+l Place <label> for the axis. Use +L to enforce horizontal labels for y-axes. "
"For another axis label on the opposite axis, use +s|S as well. "
Expand All @@ -7194,6 +7205,8 @@ void gmtlib_explain_options (struct GMT_CTRL *GMT, char *options) {
"A <label> may contain LaTeX code enclosed by @[ .... @[ (or alternatively <math> ... </math>). "
"Using LaTeX expressions requires you to have a functioning latex and dvips installation, including required fonts. "
"Geographic map annotations will automatically have degree, minute, seconds units.");
GMT_Usage (API, 3, "+p Prepend <prefix> to each annotation (e.g., $ 10, $ 20 ...).");
GMT_Usage (API, 3, "+u Append <unit> to each annotation (e.g., 5 km, 10 km ...).");
GMT_Usage (API, -2, "See basemap documentation for more details and examples of all settings.");
break;

Expand All @@ -7203,7 +7216,7 @@ void gmtlib_explain_options (struct GMT_CTRL *GMT, char *options) {
GMT_Usage (API, 2, "Frame settings are modified via an optional single invocation of "
"-B[<axes>][+b][+g<fill>][+i[<val>]][+n][+o<lon>/<lat>][+s<subtitle>][+t<title>][+w[<pen>]][+x<fill>][+y<fill>][+z<fill>]");
GMT_Usage (API, 2, "Axes parameters are specified via one or more invocations of "
"-B[p|s][x|y|z]<intervals>[+a<angle>|n|p][+f][+l|L<label>][+p<prefix>][+s|S<secondary_label>][+u<unit>");
"-B[p|s][x|y|z]<intervals>[+a<angle>|n|p][+e[l|u]][+f][+l|L<label>][+p<prefix>][+s|S<secondary_label>][+u<unit>");
GMT_Usage (API, -2, "<intervals> is composed of concatenated [<type>]<stride>[l|p] sub-strings. "
"See basemap documentation for more details and examples of all settings.");
break;
Expand Down Expand Up @@ -17386,7 +17399,7 @@ int gmt_parse_common_options (struct GMT_CTRL *GMT, char *list, char option, cha
if (GMT->current.setting.run_mode == GMT_MODERN && (!GMT->current.map.frame.set[GMT_X] || !GMT->current.map.frame.set[GMT_Y] || (GMT->common.J.zactive && !GMT->current.map.frame.set[GMT_Z]))) {
char code[2], args[GMT_LEN256] = {""}, *c = strchr (item, '+'); /* Start of modifiers, if any */
if (item[q] && strstr (item, "+f")) GMT->current.plot.calclock.geo.wesn = 1; /* Got +f, so enable W|E|S|N suffices */
if (c && strchr ("aflLsSu", c[1])) /* We got the ones suitable for axes that we can chop off */
if (c && strchr (GMT_AXIS_MODIFIERS, c[1])) /* We got the ones suitable for axes that we can chop off */
c[0] = '\0'; /* Temporarily chop off these modifiers only */
code[0] = item[q]; code[1] = (item[q]) ? item[q+1] : '\0';
if (c) c[0] = '+'; /* Restore modifiers */
Expand Down
2 changes: 1 addition & 1 deletion src/gmt_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ GMT_LOCAL struct GMT_OPTION * gmtparse_ensure_b_and_dash_options_order (struct G
this_priority = 2;
n_B++;
}
else if ((c = gmt_first_modifier (GMT, opt->arg, "aflLpsSu"))) { /* Option has axis modifier(s) */
else if ((c = gmt_first_modifier (GMT, opt->arg, GMT_AXIS_MODIFIERS))) { /* Option has axis modifier(s) */
c[0] = '\0'; /* Temporary chop them off */
j = 0; /* Start of option string, then advance past any leading [p|s][x|y|z] */
if (strchr ("ps", opt->arg[j])) j++;
Expand Down
16 changes: 13 additions & 3 deletions src/gmt_plot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,14 @@ GMT_LOCAL double gmtplot_curved_boundary_offset (struct GMT_CTRL *GMT, double lo
return boost;
}

GMT_LOCAL bool gmtplot_skip_end_annotation (struct GMT_CTRL *GMT, unsigned int axis, double x, double length) {
/* Returns true if this is an annotation at the end of the axis and we are either in GMT_IS_INSIDE mode or user added modifer +e[l|u] to the axis annotation settings */
if (GMT->current.map.frame.axis[axis].skip[0] && fabs (x) < GMT_CONV4_LIMIT) return true; /* Skip annotation if it falls ~exactly at the start of the axis */
if (GMT->current.map.frame.axis[axis].skip[1] && fabs (x - length) < GMT_CONV4_LIMIT) return true; /* Skip annotation if t falls ~exactly at the end of the axis */
if (GMT->current.setting.map_frame_type & GMT_IS_INSIDE && (fabs (x) < GMT_CONV4_LIMIT || fabs (x - length) < GMT_CONV4_LIMIT)) return true; /* Skip annotation on edges when MAP_FRAME_TYPE = inside */
return false; /* No, let's plot it */
}

GMT_LOCAL void gmtplot_map_symbol (struct GMT_CTRL *GMT, struct PSL_CTRL *PSL, struct GMT_XINGS *xings, char *label, unsigned int type, bool annot, unsigned int level, unsigned int form) {
/* type = 0 for lon and 1 for lat */

Expand Down Expand Up @@ -1807,7 +1815,10 @@ GMT_LOCAL void gmtplot_map_symbol (struct GMT_CTRL *GMT, struct PSL_CTRL *PSL, s
}

if (annot) {
double length = (type == GMT_X) ? GMT->current.map.width : GMT->current.map.height;
double pos = (type == GMT_X) ? xx[i] : yy[i];
if (gmtplot_annot_too_crowded (GMT, xx[i], yy[i], sides[i])) continue;
if (gmtplot_skip_end_annotation (GMT, type, pos, length)) continue; /* Don't want annotations exactly at one or both ends of the axis */
if (GMT->current.proj.three_D && GMT->current.proj.z_project.cos_az > 0) { /* Rotate annotation when seen "from North" */
if (!flip) justify = gmt_flip_justify (GMT, justify);
text_angle += 180.0;
Expand Down Expand Up @@ -5570,7 +5581,6 @@ void gmt_xy_axis (struct GMT_CTRL *GMT, double x0, double y0, double length, dou
for (i = 0; i < nx; i++) {
x = (*xyz_fwd) (GMT, knots[i]); /* Convert to inches on the page */
if (x < (- GMT_CONV4_LIMIT) || x > (length + GMT_CONV4_LIMIT)) continue; /* Outside the range */
if (GMT->current.setting.map_frame_type & GMT_IS_INSIDE && (fabs (x) < GMT_CONV4_LIMIT || fabs (x - length) < GMT_CONV4_LIMIT)) continue; /* Skip annotation on edges when MAP_FRAME_TYPE = inside */
if (gmtplot_skip_second_annot (k, knots[i], knots_p, np, primary)) continue; /* Minor tick marks skipped when coinciding with major */
if (horizontal)
PSL_plotsegment (PSL, x, 0.0, x, ((neg) ? -1.0 : 1.0) * GMT->current.setting.map_tick_length[k]);
Expand All @@ -5597,7 +5607,7 @@ void gmt_xy_axis (struct GMT_CTRL *GMT, double x0, double y0, double length, dou
if (gmtlib_annot_pos (GMT, val0, val1, T, &knots[i], &t_use)) continue; /* Outside range */
if (axis == GMT_Z && fabs (knots[i] - GMT->current.proj.z_level) < GMT_CONV8_LIMIT) continue; /* Skip z annotation coinciding with z-level plane */
x = (*xyz_fwd) (GMT, knots[i]); /* Convert to inches on the page */
if (GMT->current.setting.map_frame_type & GMT_IS_INSIDE && (fabs (x) < GMT_CONV4_LIMIT || fabs (x - length) < GMT_CONV4_LIMIT)) continue; /* Skip annotation on edges when MAP_FRAME_TYPE = inside */
if (gmtplot_skip_end_annotation (GMT, axis, x, length)) continue; /* Don't want annotations exactly at one or both ends of the axis */
if (!is_interval && gmtplot_skip_second_annot (k, knots[i], knots_p, np, primary)) continue; /* Secondary annotation skipped when coinciding with primary annotation */
if (label_c && label_c[i] && label_c[i][0]) {
strncpy (string, label_c[i], GMT_LEN256-1);
Expand Down Expand Up @@ -5636,7 +5646,7 @@ void gmt_xy_axis (struct GMT_CTRL *GMT, double x0, double y0, double length, dou
if (gmtlib_annot_pos (GMT, val0, val1, T, &knots[i], &t_use)) continue; /* Outside range */
if (axis == GMT_Z && fabs (knots[i] - GMT->current.proj.z_level) < GMT_CONV8_LIMIT) continue; /* Skip z annotation coinciding with z-level plane */
x = (*xyz_fwd) (GMT, t_use); /* Convert to inches on the page */
if (GMT->current.setting.map_frame_type & GMT_IS_INSIDE && (fabs (x) < GMT_CONV4_LIMIT || fabs (x - length) < GMT_CONV4_LIMIT)) continue; /* Skip annotation on edges when MAP_FRAME_TYPE = inside */
if (gmtplot_skip_end_annotation (GMT, axis, x, length)) continue; /* Don't want annotations exactly at one or both ends of the axis */
if (!is_interval && gmtplot_skip_second_annot (k, knots[i], knots_p, np, primary)) continue; /* Secondary annotation skipped when coinciding with primary annotation */
/* Move to new anchor point */
PSL_command (PSL, "%d PSL_A%d_y MM\n", PSL_IZ (PSL, x), annot_pos);
Expand Down
1 change: 1 addition & 0 deletions src/gmt_project.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ struct GMT_PLOT_AXIS { /* Information for one time axis */
unsigned int label_mode; /* 0 = parallel to all axes, 1 = always horizontal on map */
bool substitute_pi; /* True if we need to plot fractions of pi on this axis */
bool use_angle; /* True if we got +a<angle>|n|p for this axis */
bool skip[2]; /* Determins if we skip annotations at the lower or upper bounds of an axis [false/false] */
struct GMT_PLOT_AXIS_ITEM item[8]; /* see above defines for which is which */
double phase; /* Phase offset for strides: (knot-phase)%interval = 0 */
double angle; /* Annotations angle set by user */
Expand Down
Binary file added test/psbasemap/skipannots.ps
Binary file not shown.
19 changes: 19 additions & 0 deletions test/psbasemap/skipannots.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# Test the new +e modifier to -B
gmt begin skipannots ps
gmt set MAP_FRAME_TYPE plain PS_MEDIA letter
echo "-Bx -By" | gmt text -R0/80/0/30 -Jx0.1c -Bx -By -F+cCM+f14p -Y1.25c
echo "-Bx+e -By" | gmt text -Bx+e -By -Y3.75c -F+cCM+f14p
echo "-Bx+el -By" | gmt text -Bx+el -By -Y3.75c -F+cCM+f14p
echo "-Bx+eu -By" | gmt text -Bx+eu -By -Y3.75c -F+cCM+f14p
echo "-Bx -By+e" | gmt text -Bx -By+e -Y3.75c -F+cCM+f14p
echo "-Bx -By+el" | gmt text -Bx -By+el -Y3.75c -F+cCM+f14p
echo "-Bx -By+eu" | gmt text -Bx -By+eu -Y3.75c -F+cCM+f14p
echo "-Bx -By" | gmt text -R0/60/0/30 -Jq0.1c -Bx -By -X10c -F+cCM+f14p
echo "-Bx+e -By+el" | gmt text -Bx+e -By+el -Y-3.75c -F+cCM+f14p
echo "-Bx+e -By+eu" | gmt text -Bx+e -By+eu -Y-3.75c -F+cCM+f14p
echo "-Bx+e -By+e" | gmt text -Bx+e -By+e -Y-3.75c -F+cCM+f14p
echo "-Bx+el -By+el" | gmt text -Bx+el -By+el -Y-3.75c -F+cCM+f14p
echo "-Bx+el -By+eu" | gmt text -Bx+el -By+eu -Y-3.75c -F+cCM+f14p
echo "-Bx+eu -By+eu" | gmt text -Bx+eu -By+eu -Y-3.75c -F+cCM+f14p
gmt end show