From 97193de62dfb478de00dd7038699aaa8383664fa Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Mon, 11 Dec 2023 14:09:28 +0100 Subject: [PATCH 1/2] Fix failure to honor +a angle in decorated lines Simply did not pass the fixed angle when it was set and ended up passing the line angle which was zero. --- src/gmt_support.c | 2 +- src/psxy.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gmt_support.c b/src/gmt_support.c index 1ff443a9926..6e68ffedee5 100644 --- a/src/gmt_support.c +++ b/src/gmt_support.c @@ -3411,7 +3411,7 @@ GMT_LOCAL void gmtsupport_add_decoration (struct GMT_CTRL *GMT, struct GMT_DATAS S->data[GMT_X][S->n_rows] = L->x; S->data[GMT_Y][S->n_rows] = L->y; S->data[GMT_Z][S->n_rows] = gmt_M_to_inch (GMT, G->size); - S->data[3][S->n_rows] = L->line_angle; /* Change this in inches internally instead of string */ + S->data[3][S->n_rows] = (G->angle_type == GMT_ANGLE_LINE_FIXED) ? G->symbol_angle : L->line_angle; S->text[S->n_rows++] = strdup (G->symbol_code); } diff --git a/src/psxy.c b/src/psxy.c index a00600b8097..b170c3bc1da 100644 --- a/src/psxy.c +++ b/src/psxy.c @@ -442,7 +442,7 @@ GMT_LOCAL int psxy_plot_decorations (struct GMT_CTRL *GMT, struct GMT_DATASET *D return (GMT->parent->error); tmp_file[len] = '.'; /* Restore the ".def" extension so we can delete the file (unless -Vd) */ if (gmt_M_is_verbose (GMT, GMT_MSG_DEBUG)) { /* Leave the symbol def and txt files in the temp directory */ - char tmp_file2[GMT_LEN64] = {""}; + char tmp_file2[GMT_LEN128] = {""}; bool was = GMT->current.setting.io_header[GMT_OUT]; /* Save current setting */ GMT_Report (GMT->parent, GMT_MSG_DEBUG, "Temporary symbol file for decorated lines saved: %s\n", tmp_file); if (GMT->parent->tmp_dir) /* Make unique file in tmp dir */ From 06e49afbe15e4332ec30b32c9586d4b401392136 Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Mon, 11 Dec 2023 14:50:59 +0100 Subject: [PATCH 2/2] Fix bug and allow +apangle for decorated lines This fixes the bug in #7591. While at it, we allow +apangle to let the symbol angle deviate by angle from the line's angle.+aangle still sets a fixed angle regardless of angle contortions. --- doc/rst/source/explain_symbols.rst_ | 3 ++- src/gmt_contour.h | 3 ++- src/gmt_decorate.h | 2 +- src/gmt_init.c | 3 ++- src/gmt_support.c | 24 +++++++++++++++++++++--- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/doc/rst/source/explain_symbols.rst_ b/doc/rst/source/explain_symbols.rst_ index 5c40b1f92b5..6d5dc9ab099 100644 --- a/doc/rst/source/explain_symbols.rst_ +++ b/doc/rst/source/explain_symbols.rst_ @@ -616,7 +616,8 @@ **+a**\ *angle* Force symbols at a fixed angle, **+an** for line-normal, or - **+ap** for line-parallel [Default]. + **+ap** for line-parallel [Default]. Use **p**\ *angle* to set a + constant deviation from line-parallel. **+d**\ [*pen*] Turn on debug, which will draw helper points and lines to illustrate diff --git a/src/gmt_contour.h b/src/gmt_contour.h index beac8618a74..b38ee227d1f 100644 --- a/src/gmt_contour.h +++ b/src/gmt_contour.h @@ -41,7 +41,8 @@ enum GMT_enum_contline { enum GMT_enum_contangle { GMT_ANGLE_LINE_PARALLEL = 0, /* Angles follows the line locally */ GMT_ANGLE_LINE_NORMAL, /* Angles is normal to the line locally */ - GMT_ANGLE_LINE_FIXED}; /* Angle is fixed regardless of line direction */ + GMT_ANGLE_LINE_FIXED, /* Angle is fixed regardless of line direction */ + GMT_ANGLE_LINE_DELTA}; /* Angle is a fixed offset from line direction */ /*! Various settings for quoted line/contour label types */ diff --git a/src/gmt_decorate.h b/src/gmt_decorate.h index 26b980717db..79fda5d9e19 100644 --- a/src/gmt_decorate.h +++ b/src/gmt_decorate.h @@ -54,7 +54,7 @@ struct GMT_DECORATE { unsigned int nx; /* Number of crossovers at any time */ unsigned int f_n; /* Number of such points */ unsigned int nudge_flag; /* 0 if off, 1 if nudging relative to x/y axis, 2 if following local line coordinate system */ - unsigned int angle_type; /* 0 = line-parallel (GMT_ANGLE_LINE_PARALLEL), 1 = line-normal (GMT_ANGLE_LINE_NORMAL), 2 = fixed angle (GMT_ANGLE_LINE_FIXED) */ + unsigned int angle_type; /* 0 = line-parallel (GMT_ANGLE_LINE_PARALLEL), 1 = line-normal (GMT_ANGLE_LINE_NORMAL), 2 = fixed angle (GMT_ANGLE_LINE_FIXED), 3 = fixed delta angle (GMT_ANGLE_LINE_DELTA) */ int number_placement; /* How the n_cont symbols are distributed [-1/0/+1]*/ bool isolate; /* true if we have a limit on how close symbols may appear (see below) */ bool segmentize; /* true if we should segmentize input lines before plotting */ diff --git a/src/gmt_init.c b/src/gmt_init.c index cd50f5cd401..7d66fe2c7f6 100644 --- a/src/gmt_init.c +++ b/src/gmt_init.c @@ -8592,7 +8592,8 @@ void gmt_label_syntax (struct GMT_CTRL *GMT, unsigned int indent, unsigned int k } else { GMT_Usage (API, indent, "+a Place all %s at a fixed . " - "Or, specify +an (line-normal) or +ap (line-parallel) [Default].", feature[kind]); + "Or, specify +an (line-normal) or +ap (line-parallel) [Default]. If p is appended then + is used as a fixed deviation from the line orientation", feature[kind]); } if (kind < 2) GMT_Usage (API, indent, "+c Set clearance [/] between label and text box [15%%]."); GMT_Usage (API, indent, "+d Debug mode which draws helper points and lines; optionally add a pen [%s].", gmt_putpen (GMT, &GMT->current.setting.map_default_pen)); diff --git a/src/gmt_support.c b/src/gmt_support.c index 6e68ffedee5..f272dd8dbc2 100644 --- a/src/gmt_support.c +++ b/src/gmt_support.c @@ -2233,6 +2233,12 @@ GMT_LOCAL void gmtsupport_line_angle_ave (struct GMT_CTRL *GMT, double x[], doub if (fabs (L->line_angle - angle) > 145.0) L->line_angle += 180.0; } } + if (angle_type == GMT_ANGLE_LINE_DELTA) { /* Add delta angle to line angle */ + if (gmt_M_is_dnan (cangle)) /* Cannot use this angle - default to along-line angle */ + angle_type = GMT_ANGLE_LINE_PARALLEL; + else + L->angle = L->line_angle + cangle; + } if (angle_type == GMT_ANGLE_LINE_FIXED) { /* Just return the fixed angle given (unless NaN) */ if (gmt_M_is_dnan (cangle)) /* Cannot use this angle - default to along-line angle */ angle_type = GMT_ANGLE_LINE_PARALLEL; @@ -3387,6 +3393,7 @@ GMT_LOCAL void gmtsupport_hold_contour_sub (struct GMT_CTRL *GMT, double **xxx, /*! . */ GMT_LOCAL void gmtsupport_add_decoration (struct GMT_CTRL *GMT, struct GMT_DATASEGMENT *S, struct GMT_LABEL *L, struct GMT_DECORATE *G) { /* Add a symbol location to the growing segment */ + double angle; struct GMT_DATASEGMENT_HIDDEN *SH = gmt_get_DS_hidden (S); if (S->n_rows == SH->n_alloc) { /* Need more memory for the segment */ uint64_t col; @@ -3411,7 +3418,10 @@ GMT_LOCAL void gmtsupport_add_decoration (struct GMT_CTRL *GMT, struct GMT_DATAS S->data[GMT_X][S->n_rows] = L->x; S->data[GMT_Y][S->n_rows] = L->y; S->data[GMT_Z][S->n_rows] = gmt_M_to_inch (GMT, G->size); - S->data[3][S->n_rows] = (G->angle_type == GMT_ANGLE_LINE_FIXED) ? G->symbol_angle : L->line_angle; + if (G->angle_type == GMT_ANGLE_LINE_DELTA) angle = G->symbol_angle + L->line_angle; + else if (G->angle_type == GMT_ANGLE_LINE_FIXED) angle = G->symbol_angle; + else angle = L->line_angle; + S->data[3][S->n_rows] = angle; S->text[S->n_rows++] = strdup (G->symbol_code); } @@ -10959,8 +10969,16 @@ int gmtlib_decorate_specs (struct GMT_CTRL *GMT, char *txt, struct GMT_DECORATE while ((gmt_strtok (specs, "+", &pos, p))) { switch (p[0]) { case 'a': /* Angle specification */ - if (p[1] == 'p' || p[1] == 'P') /* Line-parallel label */ - G->angle_type = GMT_ANGLE_LINE_PARALLEL; + if (p[1] == 'p' || p[1] == 'P') { /* Line-parallel label */ + if (p[2]) { /* Gave optional fixed angle deviation from line-parallel */ + G->angle_type = GMT_ANGLE_LINE_DELTA; + G->symbol_angle = atof (&p[2]); + gmt_lon_range_adjust (GMT_IS_M180_TO_P180_RANGE, &G->symbol_angle); /* Now -180/+180 */ + while (fabs (G->symbol_angle) > 90.0) G->symbol_angle -= copysign (180.0, G->symbol_angle); + } + else + G->angle_type = GMT_ANGLE_LINE_PARALLEL; + } else if (p[1] == 'n' || p[1] == 'N') /* Line-normal label */ G->angle_type = GMT_ANGLE_LINE_NORMAL; else { /* Label at a fixed angle */