Skip to content
Open
3 changes: 2 additions & 1 deletion src/gmt_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,8 @@ enum GMT_enum_inonout {GMT_IOO_UNKNOWN = 0, /* Decide based on range and type */
GMT_IOO_SPHERICAL}; /* Use spherical inside function */

enum GMT_enum_path {GMT_RESAMPLE_PATH = 0, /* Default: Resample geographic paths based in a max gap allowed (path_step) */
GMT_LEAVE_PATH}; /* Options like -A can turn off this resampling, where available */
GMT_LEAVE_PATH, /* Options like -A can turn off this resampling, where available */
GMT_STRAIGHT_PATH}; /* As GMT_LEAVE_PATH, and geographic points are also joined by straight lines on the map (-A) */

enum GMT_enum_stairpath {GMT_STAIRS_OFF = 0, /* Default: No stairclimbing */
GMT_STAIRS_Y, /* Move vertically (meridian) to next point along y, then horizontally along x */
Expand Down
35 changes: 27 additions & 8 deletions src/gmt_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@
#include "gmt_dev.h"
#include "gmt_internals.h"

/* With -A geographic points are joined by straight lines on the map, so these are never split or wrapped */
#define gmtmap_straight_path(GMT) (GMT->current.map.path_mode == GMT_STRAIGHT_PATH && gmt_M_is_geographic (GMT, GMT_IN) && (gmt_M_is_cylindrical (GMT) || gmt_M_is_perspective (GMT) || gmt_M_is_misc (GMT)))

/* We put all the declaration of external functions from gmt_proj.h here since
* (a) they are only called in gmt_map.c so no need to go in gmt_internals.h
* (b) this will change completely when proj4 is relacing gmt_proj in GMT 6.
Expand Down Expand Up @@ -806,7 +809,7 @@ GMT_LOCAL unsigned int gmtmap_wesn_crossing (struct GMT_CTRL *GMT, double lon0,
* then move the western-most point east if it is further than 180 degrees away.
* This may cause the points to span the eastern boundary */

if (GMT->current.map.lon_wrap) {
if (GMT->current.map.lon_wrap && !gmtmap_straight_path (GMT)) { /* No short-way wrapping for straight lines */
while (lon0 < GMT->common.R.wesn[XLO]) lon0 += GMT->current.map.lon_wrap_range;
while (lon0 > GMT->common.R.wesn[XHI]) lon0 -= GMT->current.map.lon_wrap_range;
while (lon1 < GMT->common.R.wesn[XLO]) lon1 += GMT->current.map.lon_wrap_range;
Expand Down Expand Up @@ -855,7 +858,7 @@ GMT_LOCAL unsigned int gmtmap_wesn_crossing (struct GMT_CTRL *GMT, double lon0,
}

/* Now adjust the longitudes so that they might span the western boundary */
if (GMT->current.map.lon_wrap && MAX(lon0, lon1) > GMT->common.R.wesn[XHI]) {
if (GMT->current.map.lon_wrap && !gmtmap_straight_path (GMT) && MAX(lon0, lon1) > GMT->common.R.wesn[XHI]) {
lon0 -= GMT->current.map.lon_wrap_range; lon1 -= GMT->current.map.lon_wrap_range;
}
else if (GMT->current.map.lat_wrap && MAX(lat0, lat1) > GMT->common.R.wesn[YHI]) {
Expand Down Expand Up @@ -1150,6 +1153,8 @@ GMT_LOCAL int gmtmap_jump_x (struct GMT_CTRL *GMT, double x0, double y0, double
/* true if x-distance between points exceeds 1/2 map width at this y value */
double dx, map_half_size, half_lon_range;

if (gmtmap_straight_path (GMT)) return (0); /* Straight lines are never split */

if (!(gmt_M_is_cylindrical (GMT) || gmt_M_is_perspective (GMT) || gmt_M_is_misc (GMT))) return (0); /* Only projections with periodic boundaries may apply */

if (gmt_M_is_cartesian (GMT, GMT_IN) || fabs (GMT->common.R.wesn[XLO] - GMT->common.R.wesn[XHI]) < 90.0) return (0);
Expand All @@ -1161,11 +1166,16 @@ GMT_LOCAL int gmtmap_jump_x (struct GMT_CTRL *GMT, double x0, double y0, double
dx = x1 - x0;
if (fabs (dx) > map_half_size) { /* Possible jump; let's see how far apart those longitudes really are */
/* This test on longitudes was added to deal with issue #672, also see test/psxy/nojump.sh */
double last_lon = 0.0, this_lon = 0.0, dummy = 0.0, dlon;
double last_lon = 0.0, this_lon = 0.0, dummy = 0.0, dlon, d0, d1, mid_lon;
gmt_xy_to_geo (GMT, &last_lon, &dummy, x0, y0);
gmt_xy_to_geo (GMT, &this_lon, &dummy, x1, y1);
gmt_M_set_delta_lon (last_lon, this_lon, dlon); /* Beware of jumps due to sign differences */
if (fabs (dlon) < half_lon_range) /* Not going the long way so we judge this to be no jump */
if (fabs (dlon) < half_lon_range) /* Gap is less than half the region width so we judge this to be no jump */
return (0);
mid_lon = 0.5 * (GMT->common.R.wesn[XLO] + GMT->common.R.wesn[XHI]);
gmt_M_set_delta_lon (mid_lon, last_lon, d0); /* Longitudes relative to the middle of the region */
gmt_M_set_delta_lon (mid_lon, this_lon, d1);
if (fabs (d1 - d0) < 180.0) /* The straight path is the short way, so no jump */
return (0);
/* Jump it is */
if (dx > map_half_size) return (-1); /* Cross left/west boundary */
Expand All @@ -1179,6 +1189,8 @@ GMT_LOCAL int gmtmap_jump_xy (struct GMT_CTRL *GMT, double x0, double y0, double
bool periodic;
double dx, dy, map_half_width, map_half_height;

if (gmtmap_straight_path (GMT)) return (0); /* Straight lines are never split */

if (!(gmt_M_is_cylindrical (GMT) || gmt_M_is_perspective (GMT) || gmt_M_is_misc (GMT))) return (0); /* Only projections with periodic boundaries may apply */

if (gmt_M_is_cartesian (GMT, GMT_IN) || fabs (GMT->common.R.wesn[XLO] - GMT->common.R.wesn[XHI]) < 90.0) return (0);
Expand Down Expand Up @@ -1340,6 +1352,10 @@ GMT_LOCAL int gmtmap_eqdist_crossing (struct GMT_CTRL *GMT, double lon1, double

/*! . */
GMT_LOCAL unsigned int gmtmap_crossing (struct GMT_CTRL *GMT, double lon1, double lat1, double lon2, double lat2, double *xlon, double *xlat, double *xx, double *yy, unsigned int *sides) {
if (gmtmap_straight_path (GMT)) { /* Use the longitudes as plotted */
gmt_M_wind_lon (GMT, lon1); lon1 += GMT->current.proj.central_meridian;
gmt_M_wind_lon (GMT, lon2); lon2 += GMT->current.proj.central_meridian;
}
if (GMT->current.map.prev_x_status == GMT->current.map.this_x_status && GMT->current.map.prev_y_status == GMT->current.map.this_y_status) {
/* This is naive. We could have two points outside with a line drawn between crossing the plotting area. */
return (0);
Expand Down Expand Up @@ -1799,7 +1815,7 @@ uint64_t gmt_map_wesn_clip (struct GMT_CTRL *GMT, double *lon, double *lat, uint
}
}
else { /* Don't let points be > 180 from center longitude */
double mid_lon = 0.5 * (border[GMT_LEFT] + border[GMT_RIGHT]), diff;
double mid_lon = (gmtmap_straight_path (GMT)) ? GMT->current.proj.central_meridian : 0.5 * (border[GMT_LEFT] + border[GMT_RIGHT]), diff;
for (i = 0; i < n; i++) {
diff = lon[i] - mid_lon;
if (diff > 180.0) lon[i] -= 360.0;
Expand Down Expand Up @@ -5644,7 +5660,7 @@ GMT_LOCAL bool gmtmap_will_it_wrap_x (struct GMT_CTRL *GMT, double *x, double *y
bool wrap;
double w_last, w_this;

if (!GMT->current.map.is_world) return (false);
if (!GMT->current.map.is_world || gmtmap_straight_path (GMT)) return (false);
//if (!GMT->current.map.is_world)
// f = (2.0 - GMT_CONV8_LIMIT);
w_this = gmt_half_map_width (GMT, y[0]);
Expand Down Expand Up @@ -7646,6 +7662,9 @@ bool gmt_map_outside (struct GMT_CTRL *GMT, double lon, double lat) {
GMT_Report (GMT->parent, GMT_MSG_ERROR, "gmt_map_outside: FATAL ERROR - the pointer to the projection function is NULL.\n");
return GMT_NOTSET;
}
if (gmtmap_straight_path (GMT)) { /* Use the longitude as plotted */
gmt_M_wind_lon (GMT, lon); lon += GMT->current.proj.central_meridian;
}
return ((*GMT->current.map.outside) (GMT, lon, lat));
}

Expand Down Expand Up @@ -8281,7 +8300,7 @@ GMT_LOCAL bool gmtmap_accept_the_jump (struct GMT_CTRL *GMT, double lon1, double
double dlon0, dlon1, dlon;
int xm, ym;
gmt_M_unused(xx);
if (cartesian) return true; /* No wrap issues if Cartesian x,y */
if (cartesian || gmtmap_straight_path (GMT)) return true; /* No wrap issues if Cartesian x,y or straight lines */
xm = GMT->current.map.this_x_status - GMT->current.map.prev_x_status;
ym = GMT->current.map.this_y_status - GMT->current.map.prev_y_status;
gmt_M_set_delta_lon (lon0, GMT->current.proj.central_meridian, dlon0);
Expand Down Expand Up @@ -8366,7 +8385,7 @@ uint64_t gmt_geo_to_xy_line(struct GMT_CTRL *GMT, double *lon, double *lat, uint
}

if ((nx = gmtmap_crossing (GMT, lon[j-1], lat[j-1], lon[j], lat[j], xlon, xlat, xx, yy, sides))) { /* Do nothing if we get crossings*/ }
else if (GMT->current.map.is_world && /* Check global wrapping if 360 range */
else if (GMT->current.map.is_world && !gmtmap_straight_path (GMT) && /* Check global wrapping if 360 range */
!(gmt_M_is_azimuthal (GMT) && !gmt_M_is_perspective (GMT))) /* Azimuthal projections (except ortho/genper) have a closed boundary; cylindrical wrap check makes spurious chord crossings (#8684) */
nx = (*GMT->current.map.wrap_around_check) (GMT, dummy, last_x, last_y, this_x, this_y, xx, yy, sides);

Expand Down
2 changes: 1 addition & 1 deletion src/gmt_vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -1529,7 +1529,7 @@ void gmt_set_line_resampling (struct GMT_CTRL *GMT, bool active, unsigned int mo
* By default, path_mode = GMT_RESAMPLE_PATH = 0. */

if (gmt_M_is_geographic (GMT, GMT_IN)) { /* Geographic data: Default is to resample along great circles unless -A given */
if (active && mode == GMT_STAIRS_OFF) GMT->current.map.path_mode = GMT_LEAVE_PATH; /* Turn off resampling */
if (active && mode == GMT_STAIRS_OFF) GMT->current.map.path_mode = GMT_STRAIGHT_PATH; /* Turn off resampling and join points by straight lines on the map */
}
else { /* Cartesian data: Default is to leave alone unless -Ax|y was set */
if (!active) GMT->current.map.path_mode = GMT_LEAVE_PATH; /* Turn off resampling */
Expand Down
3 changes: 2 additions & 1 deletion src/psxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,7 @@ EXTERN_MSC int GMT_psxy (void *V_API, int mode, void *args) {
}

gmt_set_line_resampling (GMT, Ctrl->A.active, Ctrl->A.mode); /* Possibly change line resampling mode */
if (not_line && GMT->current.map.path_mode == GMT_STRAIGHT_PATH) GMT->current.map.path_mode = GMT_LEAVE_PATH; /* -A only makes lines straight, not symbols */
#ifdef DEBUG
/* Change default step size (in degrees) used for interpolation of line segments along great circles (if requested) */
if (Ctrl->A.active) Ctrl->A.step = Ctrl->A.step / GMT->current.proj.scale[GMT_X] / GMT->current.proj.M_PR_DEG;
Expand Down Expand Up @@ -2491,7 +2492,7 @@ EXTERN_MSC int GMT_psxy (void *V_API, int mode, void *args) {
struct GMT_DATASET_HIDDEN *DH = NULL;
struct GMT_DATASEGMENT_HIDDEN *SH = NULL;

if (Ctrl->W.pen.mode == PSL_BEZIER && GMT->current.map.path_mode != GMT_LEAVE_PATH) /* Turn off path-resampling if Bezier */
if (Ctrl->W.pen.mode == PSL_BEZIER && GMT->current.map.path_mode == GMT_RESAMPLE_PATH) /* Turn off path-resampling if Bezier */
GMT->current.map.path_mode = GMT_LEAVE_PATH;

if (!no_line_clip) gmt_map_clip_on (GMT, GMT->session.no_rgb, 3);
Expand Down
3 changes: 2 additions & 1 deletion test/baseline/psxy.dvc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
outs:
- md5: fd04135cb8226c86f8f109e5dca463fe.dir
- md5: 6dbbc75aa2f8752b1450e4f22b7656f2.dir
nfiles: 147
path: psxy
hash: md5
size: 9555170
2 changes: 0 additions & 2 deletions test/psxy/nojump.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#!/usr/bin/env bash
# GMT_KNOWN_FAILURE
# Added after issue #672 which exposed a map jump that should not happen
# Fixed in r14052 but we keep this test in case it resurfaces
# Well, bottom panel plots the wrong closed polygon
ps=nojump.ps
cat << EOF > t.txt
115 -20
Expand Down
Loading