Skip to content

Commit 9ca8bc6

Browse files
committed
pscoat: stray lines with -JE
Fix #4617 Assisted-by: Claude Opus 4.7
1 parent 4a8878c commit 9ca8bc6

2 files changed

Lines changed: 44 additions & 7 deletions

File tree

src/gmt_map.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7976,7 +7976,7 @@ uint64_t gmtlib_lonpath (struct GMT_CTRL *GMT, double lon, double lat1, double l
79767976
uint64_t n, k;
79777977
int n_try, pos;
79787978
bool keep_trying;
7979-
double dlat, dlat0, *tlon = NULL, *tlat = NULL, x0, x1, y0, y1, d, min_gap;
7979+
double dlat, dlat0, *tlon = NULL, *tlat = NULL, x0, x1, y0, y1, d, min_gap, final_d, x_prev, y_prev;
79807980

79817981
if (GMT->current.map.meridian_straight == 2) { /* Special non-sampling for gmtselect/grdlandmask */
79827982
gmt_M_malloc2 (GMT, tlon, tlat, 2U, NULL, double);
@@ -8041,10 +8041,26 @@ uint64_t gmtlib_lonpath (struct GMT_CTRL *GMT, double lon, double lat1, double l
80418041
keep_trying = false;
80428042
}
80438043
} while (keep_trying && n_try < 10);
8044+
/* See gmtlib_lonpath above (#8684). Limit to azimuthal full-sphere case to avoid
8045+
* affecting projections where large chords are legitimate. */
8046+
if (gmt_M_is_azimuthal(GMT) && GMT->current.proj.f_horizon >= 180.0 - GMT_CONV4_LIMIT) {
8047+
final_d = hypot(x1 - x0, y1 - y0);
8048+
if (final_d > 5.0 * GMT->current.setting.map_line_step || gmt_M_is_dnan(x1) || gmt_M_is_dnan(y1))
8049+
tlat[n] = GMT->session.d_NaN;
8050+
}
80448051
x0 = x1; y0 = y1;
80458052
}
80468053
tlon[n] = lon;
80478054
tlat[n] = lat2;
8055+
/* Check if forced endpoint at lat2 makes a wild jump from previous sample (e.g. antipode of the
8056+
* azimuthal pole). If so, flag NaN so gmt_geo_to_xy_line breaks the polyline (#8684). */
8057+
if (n > 0 && !gmt_M_is_dnan(tlat[n-1]) && gmt_M_is_azimuthal(GMT) && GMT->current.proj.f_horizon >= 180.0 - GMT_CONV4_LIMIT) {
8058+
gmt_geo_to_xy(GMT, tlon[n-1], tlat[n-1], &x_prev, &y_prev);
8059+
gmt_geo_to_xy(GMT, tlon[n], tlat[n], &x1, &y1);
8060+
if (gmt_M_is_dnan(x1) || gmt_M_is_dnan(y1) || gmt_M_is_dnan(x_prev) || gmt_M_is_dnan(y_prev) ||
8061+
hypot(x1 - x_prev, y1 - y_prev) > 5.0 * GMT->current.setting.map_line_step)
8062+
tlat[n] = GMT->session.d_NaN;
8063+
}
80488064
n++;
80498065

80508066
if (n != n_alloc) {
@@ -8062,7 +8078,7 @@ uint64_t gmtlib_latpath (struct GMT_CTRL *GMT, double lat, double lon1, double l
80628078
uint64_t k, n;
80638079
int n_try, pos;
80648080
bool keep_trying;
8065-
double dlon, dlon0, *tlon = NULL, *tlat = NULL, x0, x1, y0, y1, d, min_gap;
8081+
double dlon, dlon0, *tlon = NULL, *tlat = NULL, x0, x1, y0, y1, d, min_gap, final_d, x_prev, y_prev;
80668082

80678083
if (GMT->current.map.parallel_straight == 2) { /* Special non-sampling for gmtselect/grdlandmask */
80688084
gmt_M_malloc2 (GMT, tlon, tlat, 2U, NULL, double);
@@ -8116,10 +8132,25 @@ uint64_t gmtlib_latpath (struct GMT_CTRL *GMT, double lat, double lon1, double l
81168132
keep_trying = false;
81178133
}
81188134
} while (keep_trying && n_try < 10);
8135+
/* If the final projected step is far larger than the desired map_line_step, the parallel
8136+
* crossed a projection singularity (antipode of azimuthal full-sphere pole). Mark with NaN
8137+
* so gmt_geo_to_xy_line breaks the polyline (#8684). */
8138+
if (gmt_M_is_azimuthal(GMT) && GMT->current.proj.f_horizon >= 180.0 - GMT_CONV4_LIMIT) {
8139+
final_d = hypot(x1 - x0, y1 - y0);
8140+
if (final_d > 5.0 * GMT->current.setting.map_line_step || gmt_M_is_dnan(x1) || gmt_M_is_dnan(y1))
8141+
tlat[n] = GMT->session.d_NaN;
8142+
}
81198143
x0 = x1; y0 = y1;
81208144
}
81218145
tlon[n] = lon2;
81228146
tlat[n] = lat;
8147+
if (n > 0 && !gmt_M_is_dnan(tlat[n-1]) && gmt_M_is_azimuthal(GMT) && GMT->current.proj.f_horizon >= 180.0 - GMT_CONV4_LIMIT) { /* Detect wild endpoint jump (#8684) */
8148+
gmt_geo_to_xy(GMT, tlon[n-1], tlat[n-1], &x_prev, &y_prev);
8149+
gmt_geo_to_xy(GMT, tlon[n], tlat[n], &x1, &y1);
8150+
if (gmt_M_is_dnan(x1) || gmt_M_is_dnan(y1) || gmt_M_is_dnan(x_prev) || gmt_M_is_dnan(y_prev) ||
8151+
hypot(x1 - x_prev, y1 - y_prev) > 5.0 * GMT->current.setting.map_line_step)
8152+
tlat[n] = GMT->session.d_NaN;
8153+
}
81238154
n++;
81248155
n_alloc = n;
81258156
gmt_M_malloc2 (GMT, tlon, tlat, 0, &n_alloc, double);
@@ -8221,7 +8252,8 @@ uint64_t gmt_geo_to_xy_line(struct GMT_CTRL *GMT, double *lon, double *lat, uint
82218252
}
82228253

82238254
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*/ }
8224-
else if (GMT->current.map.is_world) /* Check global wrapping if 360 range */
8255+
else if (GMT->current.map.is_world && /* Check global wrapping if 360 range */
8256+
!(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) */
82258257
nx = (*GMT->current.map.wrap_around_check) (GMT, dummy, last_x, last_y, this_x, this_y, xx, yy, sides);
82268258

82278259
if (nx == 1) { /* inside-outside or outside-inside; set move&clip vs draw flags */

src/gmt_proj.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,10 +2035,15 @@ GMT_LOCAL void gmtproj_azeqdist (struct GMT_CTRL *GMT, double lon, double lat, d
20352035
GMT->current.proj.n_antipoles++;
20362036
}
20372037
else {
2038-
c = d_acos (cc);
2039-
k = (gmt_M_proj_is_zero (c)) ? GMT->current.proj.EQ_RAD : GMT->current.proj.EQ_RAD * c / sin (c);
2040-
*x = k * clat * slon;
2041-
*y = k * (GMT->current.proj.cosp * slat - GMT->current.proj.sinp * t);
2038+
double sin_c, num_x, num_y;
2039+
c = d_acos(cc);
2040+
num_x = clat * slon;
2041+
num_y = GMT->current.proj.cosp * slat - GMT->current.proj.sinp * t;
2042+
/* sin(c) = sqrt(1 - cc^2) = hypot(num_x, num_y); this form avoids precision loss near the antipode (#8684) */
2043+
sin_c = hypot(num_x, num_y);
2044+
k = (gmt_M_proj_is_zero(c)) ? GMT->current.proj.EQ_RAD : GMT->current.proj.EQ_RAD * c / sin_c;
2045+
*x = k * num_x;
2046+
*y = k * num_y;
20422047
}
20432048
}
20442049

0 commit comments

Comments
 (0)