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
6 changes: 6 additions & 0 deletions src/gmt_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -4866,6 +4866,12 @@ GMT_LOCAL int gmtinit_parse5_B_frame_setting (struct GMT_CTRL *GMT, char *in) {
/* Now parse the frame choices, if any */
error += gmtinit_decode5_wesnz (GMT, text, true);

/* Issue #5635: Only set frame.draw = true when a modifier that actually requires a drawn frame outline
* is given (+w pen, +b 3D box, +w wall). Plain +t<title>, +s<subtitle>, +g<fill> must NOT cause an
* unwanted frame outline; title/subtitle render via map_annotate path, fill via plotcanvas. */
if (GMT->current.map.frame.draw_wall || (GMT->current.map.frame.draw_box & (GMT_3D_BOX | GMT_3D_WALL)))
GMT->current.map.frame.draw = true;

return (error);
}

Expand Down
37 changes: 37 additions & 0 deletions src/gmt_plot.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,8 @@ GMT_LOCAL unsigned char * gmtplot_latex_eps (struct GMT_CTRL *GMT, struct GMT_FO

/* GMT_LINEAR PROJECTION MAP BOUNDARY */

GMT_LOCAL double gmtplot_place_latex_eps(struct GMT_CTRL *GMT, double x, double y, struct GMT_FONT *F, const char *string);

GMT_LOCAL void gmtplot_linear_map_boundary (struct GMT_CTRL *GMT, struct PSL_CTRL *PSL, double w, double e, double s, double n) {
unsigned int cap = PSL->internal.line_cap;
double x_length, y_length;
Expand Down Expand Up @@ -524,6 +526,41 @@ GMT_LOCAL void gmtplot_linear_map_boundary (struct GMT_CTRL *GMT, struct PSL_CTR

PSL_comment (PSL, "Placing plot title\n");

if (GMT->current.proj.three_D) {
/* Issue #5635: place the title parallel to the rotated top edge of the map rect.
* Project the two top corners (XLO,YHI) and (XHI,YHI) at the current z-level to
* paper space, take their midpoint, offset perpendicularly outward by the title
* offset, and rotate the text to match the edge slope. */
int form, old_plane = GMT->current.proj.z_project.plane;
double old_level = GMT->current.proj.z_project.level;
double xTL, yTL, xTR, yTR, xm, ym, ex, ey, nx, ny, nlen, ang, off;
double z_for_proj = gmt_z_to_zz(GMT, GMT->current.proj.z_level);
gmt_xyz_to_xy(GMT, GMT->current.proj.rect[XLO], GMT->current.proj.rect[YHI], z_for_proj, &xTL, &yTL);
gmt_xyz_to_xy(GMT, GMT->current.proj.rect[XHI], GMT->current.proj.rect[YHI], z_for_proj, &xTR, &yTR);
ex = xTR - xTL;
ey = yTR - yTL;
ang = atan2d(ey, ex);
/* Outward (CCW perpendicular) unit normal */
nx = -ey;
ny = ex;
nlen = hypot(nx, ny);
if (nlen > 0.0) { nx /= nlen; ny /= nlen; }
off = GMT->current.setting.map_title_offset;
xm = 0.5 * (xTL + xTR) + off * nx;
ym = 0.5 * (yTL + yTR) + off * ny;
gmt_plane_perspective(GMT, -1, 0.0);
if (gmt_text_is_latex(GMT, GMT->current.map.frame.header)) {
(void)gmtplot_place_latex_eps(GMT, xm, ym, &GMT->current.setting.font_title, GMT->current.map.frame.header);
}
else {
form = gmt_setfont(GMT, &GMT->current.setting.font_title);
PSL_plottext(PSL, xm, ym, GMT->current.setting.font_title.size, GMT->current.map.frame.header, ang, -PSL_BC, form);
}
GMT->current.map.frame.plotted_header = true;
gmt_plane_perspective(GMT, old_plane, old_level);
return;
}

y_length += GMT->current.setting.map_graph_shift; /* Extra shift (set in gmt_xy_axis) for map title when we have a centered y-axis with vector */

if (!GMT->current.map.frame.draw || GMT->current.map.frame.side[N_SIDE] <= GMT_AXIS_DRAW || GMT->current.setting.map_frame_type == GMT_IS_INSIDE)
Expand Down
31 changes: 19 additions & 12 deletions src/psimage.c
Original file line number Diff line number Diff line change
Expand Up @@ -607,17 +607,19 @@ EXTERN_MSC int GMT_psimage (void *V_API, int mode, void *args) {

/* The following is needed to have psimage work correctly in perspective */

bool fake_J_only = false; /* Issue #5635: track whether we took the no-R fake-J branch so we skip the redundant re-setup */
gmt_set_basemap_orders (GMT, GMT_BASEMAP_FRAME_AFTER, GMT_BASEMAP_GRID_AFTER, GMT_BASEMAP_ANNOT_AFTER);
gmt_M_memset (wesn, 4, double);
if (!(GMT->common.R.active[RSET] && GMT->common.J.active)) { /* When no projection specified, use fake linear projection */
fake_J_only = true;
GMT->common.R.active[RSET] = true;
GMT->common.J.active = false;
gmt_parse_common_options (GMT, "J", 'J', "X1i");
gmt_parse_common_options(GMT, "J", 'J', "x1i"); /* Issue #5635: lowercase x = 1 inch per unit so wesn span = inches; uppercase X1i forced rect to 1x1 inch regardless of image size */
gmt_adjust_refpoint (GMT, Ctrl->D.refpoint, Ctrl->D.dim, Ctrl->D.off, Ctrl->D.justify, PSL_BL); /* Adjust refpoint to BL corner */
wesn[XHI] = Ctrl->D.refpoint->x + Ctrl->D.n_columns * Ctrl->D.dim[GMT_X];
wesn[YHI] = Ctrl->D.refpoint->y + Ctrl->D.n_rows * Ctrl->D.dim[GMT_Y];
gmt_M_memcpy (Rwesn, wesn, 4U, double);
strncpy (Jarg, "X1i", GMT_LEN128);
strncpy(Jarg, "x1i", GMT_LEN128);
if (gmt_map_setup (GMT, wesn)) {
if (free_GMT)
gmt_M_free (GMT, picture);
Expand Down Expand Up @@ -704,17 +706,22 @@ EXTERN_MSC int GMT_psimage (void *V_API, int mode, void *args) {
if (Ctrl->F.active) /* Draw frame outlines */
gmt_draw_map_panel (GMT, Ctrl->D.refpoint->x + 0.5 * Ctrl->F.panel->width, Ctrl->D.refpoint->y + 0.5 * Ctrl->F.panel->height, 2U, Ctrl->F.panel);

/* Redo original -R -J so basemap can work */
GMT->common.J.active = false;
gmt_parse_common_options (GMT, "J", 'J', Jarg);
if (gmt_map_setup (GMT, Rwesn)) {
if (free_GMT)
gmt_M_free (GMT, picture);
else if (is_eps || did_gray)
PSL_free (picture);
gmt_M_str_free (file);
Return (GMT_PROJECTION_ERROR);
/* Redo original -R -J so basemap can work. Issue #5635: only needed when the original -R/-J were used
* (else branch above swapped them out for a fake X1i to place the image, and now must restore them).
* In the fake-J-only branch we never swapped, so re-parsing/-setup is redundant and corrupts state. */
if (!fake_J_only) {
GMT->common.J.active = false;
gmt_parse_common_options(GMT, "J", 'J', Jarg);
if (gmt_map_setup(GMT, Rwesn)) {
if (free_GMT)
gmt_M_free(GMT, picture);
else if (is_eps || did_gray)
PSL_free(picture);
gmt_M_str_free(file);
Return (GMT_PROJECTION_ERROR);
}
}
GMT->current.map.frame.order = GMT_BASEMAP_AFTER; /* Issue #5635: ensure basemap renders AFTER content (frame, title) since this is the only call when fake_J_only */
gmt_map_basemap (GMT); /* Draw basemap if requested */
gmt_plane_perspective (GMT, -1, 0.0);
gmt_plotend (GMT);
Expand Down
Loading