diff --git a/doc/rst/source/gmt.conf.rst b/doc/rst/source/gmt.conf.rst index c094ee2431d..e9cef7c8935 100644 --- a/doc/rst/source/gmt.conf.rst +++ b/doc/rst/source/gmt.conf.rst @@ -283,10 +283,11 @@ FORMAT Parameters **D** Use :term:`FORMAT_FLOAT_OUT` for floating point degrees [default] **+D** Output longitude in the range [0,360] **-D** Output longitude in the range [-360,0] - **ddd** Fixed format integer degrees - **:** Delimiter used - **mm** Fixed format integer arc minutes - **ss** Fixed format integer arc seconds + **DDD** Fixed format integer degrees (3 digits for longitude, 2 digits for latitude) + **ddd** Integer degrees + **:** Delimiter used (this will translate to degree, minute, seconds symbols on maps) + **mm** Fixed format integer arc minutes (2 digits) + **ss** Fixed format integer arc seconds (2 digits) **.xxx** Floating fraction of previous integer field, fixed width **F** Encode sign using WESN suffix **G** Same as **F** but with a leading space before suffix diff --git a/src/gmt_io.c b/src/gmt_io.c index 551ffd1281f..a9e6f2bf78a 100644 --- a/src/gmt_io.c +++ b/src/gmt_io.c @@ -1221,7 +1221,7 @@ void gmtlib_reset_input (struct GMT_CTRL *GMT) { GMT_LOCAL void gmtio_format_geo_output (struct GMT_CTRL *GMT, bool is_lat, double geo, char *text) { int k, n_items, d, m, s, m_sec, h_pos = 0; bool minus; - char hemi[3] = {""}, *f = NULL; + char hemi[3] = {""}, *use_format = NULL; static char *suffix[2][2] = {{"W", "E"}, {"S", "N"}}; /* Just for decimal degrees when no_sign is true */ if (is_lat) { /* Column is supposedly latitudes */ @@ -1233,14 +1233,14 @@ GMT_LOCAL void gmtio_format_geo_output (struct GMT_CTRL *GMT, bool is_lat, doubl } else gmt_lon_range_adjust (GMT->current.io.geo.range, &geo); /* Adjust longitudes */ if (GMT->current.io.geo.decimal) { /* Easy */ - f = (GMT->current.io.o_format[is_lat]) ? GMT->current.io.o_format[is_lat] : GMT->current.setting.format_float_out; + use_format = (GMT->current.io.o_format[is_lat]) ? GMT->current.io.o_format[is_lat] : GMT->current.setting.format_float_out; if (GMT->current.io.geo.no_sign) { k = (geo < 0.0) ? 0 : 1; - sprintf (text, f, fabs(geo)); + sprintf (text, use_format, fabs(geo)); strcat (text, suffix[is_lat][k]); } else - sprintf (text, f, geo); + sprintf (text, use_format, geo); return; } @@ -1258,20 +1258,21 @@ GMT_LOCAL void gmtio_format_geo_output (struct GMT_CTRL *GMT, bool is_lat, doubl if (GMT->current.io.geo.order[k] >= 0) n_items++; /* How many of d, m, and s are requested as integers */ minus = gmtlib_geo_to_dms (geo, n_items, GMT->current.io.geo.f_sec_to_int, &d, &m, &s, &m_sec); /* Break up into d, m, s, and remainder */ if (minus) text[0] = '-'; /* Must manually insert leading minus sign when degree == 0 */ + use_format = (is_lat ? gmt_strrep(GMT->current.io.geo.format, "%3.3d", "%2.2d") : strdup(GMT->current.io.geo.format)); if (GMT->current.io.geo.n_sec_decimals) { /* Wanted fraction printed */ if (n_items == 3) - sprintf (&text[minus], GMT->current.io.geo.y_format, d, m, s, m_sec, hemi); + sprintf (&text[minus], use_format, d, m, s, m_sec, hemi); else if (n_items == 2) - sprintf (&text[minus], GMT->current.io.geo.y_format, d, m, m_sec, hemi); + sprintf (&text[minus], use_format, d, m, m_sec, hemi); else - sprintf (&text[minus], GMT->current.io.geo.y_format, d, m_sec, hemi); + sprintf (&text[minus], use_format, d, m_sec, hemi); } else if (n_items == 3) - sprintf (&text[minus], GMT->current.io.geo.y_format, d, m, s, hemi); + sprintf (&text[minus], use_format, d, m, s, hemi); else if (n_items == 2) - sprintf (&text[minus], GMT->current.io.geo.y_format, d, m, hemi); + sprintf (&text[minus], use_format, d, m, hemi); else - sprintf (&text[minus], GMT->current.io.geo.y_format, d, hemi); + sprintf (&text[minus], use_format, d, hemi); } /* Various functions to support {grd2xyz,xyz2grd}_func.c */ @@ -2184,10 +2185,19 @@ GMT_LOCAL int gmtio_get_dms_order (struct GMT_CTRL *GMT, char *text, struct GMT_ if (i != 0) error++; /* Only valid as first flag */ break; case 'D': /* Want to use decimal degrees using FORMAT_FLOAT_OUT [Default] */ - S->decimal = true; - if (i > 1) error++; /* Only valid as first or second flag */ + if (S->order[0] < 0) /* First time we encounter a D */ + S->order[0] = order++; + else if (text[i-1] != 'D') /* Done it before, previous char must be D */ + error++; n_DD++; break; + case 'd': /* Degree */ + if (S->order[0] < 0) /* First time we encounter a d */ + S->order[0] = order++; + else if (text[i-1] != 'd') /* Done it before, previous char must be d */ + error++; + n_d++; + break; case 'F': /* Want to use WESN to encode sign */ S->wesn = (i == 0) ? -1 : 1; if (S->no_sign) error++; /* Cannot mix A and F */ @@ -2202,13 +2212,6 @@ GMT_LOCAL int gmtio_get_dms_order (struct GMT_CTRL *GMT, char *text, struct GMT_ S->no_sign = true; if (i != i1 || S->wesn) error++; /* Only valid as last flag */ break; - case 'd': /* Degree */ - if (S->order[0] < 0) /* First time we encounter a d */ - S->order[0] = order++; - else if (text[i-1] != 'd') /* Done it before, previous char must be y */ - error++; - n_d++; - break; case 'm': /* Minute */ if (S->order[1] < 0) /* First time we encounter a m */ S->order[1] = order++; @@ -2249,6 +2252,13 @@ GMT_LOCAL int gmtio_get_dms_order (struct GMT_CTRL *GMT, char *text, struct GMT_ } } + if (n_DD > 1) { /* Leading zeros flag */ + S->leading_zeros = true; + n_d = 3; + } + else if (n_DD == 1) /* One D means decimal */ + S->decimal = true; + if (S->decimal) return (GMT_NOERROR); /* Easy formatting choice */ /* Then get the actual order by inverting table */ @@ -2271,7 +2281,6 @@ GMT_LOCAL int gmtio_get_dms_order (struct GMT_CTRL *GMT, char *text, struct GMT_ error += (n_x && n_dec != 1); /* .xxx is the proper form */ error += (n_x == 0 && n_dec); /* Period by itself and not delimiter? */ error += (n_dec > 1); /* Only one period with xxx */ - error += (n_DD > 1); /* Only one occurrence of D */ error += ((n_F > 1) || (n_G > 1)); /* Only one occurrence of F or G */ error += ((n_G + n_F) > 1); /* Only one of either F or G */ S->n_sec_decimals = n_x; @@ -7027,40 +7036,28 @@ int gmtlib_geo_C_format (struct GMT_CTRL *GMT) { /* here we depend on FORMAT_FLOAT_OUT begin set. This will not be true when FORMAT_GEO_MAP is parsed but will be * handled at the end of gmt_begin. For gmtset and --PAR later we will be OK as well. */ if (!GMT->current.setting.format_float_out[0]) return (GMT_NOERROR); /* Quietly return and deal with this later in gmt_begin */ - sprintf (S->x_format, "%s", GMT->current.setting.format_float_out); - sprintf (S->y_format, "%s", GMT->current.setting.format_float_out); + sprintf (S->format, "%s", GMT->current.setting.format_float_out); } else { /* Some form of dd:mm:ss */ char fmt[GMT_LEN64] = {""}; - /* First add %s for the W,E,S,N string (or NULL) for pre-value hemisphere */ - sprintf (fmt, "%%s"); - strcat (S->x_format, fmt); - strcat (S->y_format, fmt); - sprintf (S->x_format, "%%03d"); - sprintf (S->y_format, "%%02d"); - if (S->order[1] >= 0) { /* Need minutes too */ - strcat (S->x_format, S->delimiter[0]); - strcat (S->y_format, S->delimiter[0]); - sprintf (fmt, "%%02d"); - strcat (S->x_format, fmt); - strcat (S->y_format, fmt); + if (S->leading_zeros) + sprintf (S->format, "%%3.3d"); + else + sprintf (S->format, "%%d"); + if (S->order[1] >= 0) { /* Need minutes too */ + strcat (S->format, S->delimiter[0]); + strcat (S->format, "%02d"); } if (S->order[2] >= 0) { /* .. and seconds */ - strcat (S->x_format, S->delimiter[1]); - strcat (S->y_format, S->delimiter[1]); - sprintf (fmt, "%%02d"); - strcat (S->x_format, fmt); - strcat (S->y_format, fmt); + strcat (S->format, S->delimiter[1]); + strcat (S->format, "%02d"); } if (S->n_sec_decimals) { /* even add format for fractions of second (or minutes or degrees) */ snprintf (fmt, GMT_LEN64, ".%%%d.%dd", S->n_sec_decimals, S->n_sec_decimals); - strcat (S->x_format, fmt); - strcat (S->y_format, fmt); + strcat (S->format, fmt); } /* Finally add %s for the W,E,S,N string (or NULL) for post-value hemisphere */ - sprintf (fmt, "%%s"); - strcat (S->x_format, fmt); - strcat (S->y_format, fmt); + strcat (S->format, "%s"); } return (GMT_NOERROR); } @@ -7069,6 +7066,7 @@ int gmtlib_geo_C_format (struct GMT_CTRL *GMT) { int gmtlib_plot_C_format (struct GMT_CTRL *GMT) { unsigned int i, j, length; struct GMT_GEO_IO *S = &GMT->current.plot.calclock.geo; + char *d_fmt[2] = {"%d", "%3.3d"}; /* Determine the plot geographic location formats. */ @@ -7084,29 +7082,27 @@ int gmtlib_plot_C_format (struct GMT_CTRL *GMT) { * handled at the end of gmt_begin. For gmtset and --PAR later we will be OK as well. */ if (!GMT->current.setting.format_float_out[0]) return GMT_NOERROR; /* Quietly return and deal with this later in gmt_begin */ - len = sprintf (S->x_format, "%s", GMT->current.setting.format_float_out); - sprintf (S->y_format, "%s", GMT->current.setting.format_float_out); + len = sprintf (S->format, "%s", GMT->current.setting.format_float_out); if (GMT->current.setting.map_degree_symbol != gmt_none) { /* But we want the degree symbol appended */ - S->x_format[len] = (char)GMT->current.setting.ps_encoding.code[GMT->current.setting.map_degree_symbol]; - S->y_format[len] = (char)GMT->current.setting.ps_encoding.code[GMT->current.setting.map_degree_symbol]; - S->x_format[len+1] = S->y_format[len+1] = '\0'; + S->format[len] = (char)GMT->current.setting.ps_encoding.code[GMT->current.setting.map_degree_symbol]; + S->format[len+1] = '\0'; } - strcat (S->x_format, "%s"); - strcat (S->y_format, "%s"); + strcat (S->format, "%s"); } else { /* Must cover all the 6 forms of dd[:mm[:ss]][.xxx] */ char fmt[GMT_LEN256] = {""}; + unsigned int id = S->leading_zeros ? 1 : 0; /* Level 0: degrees only. index 0 is integer degrees, index 1 is [possibly] fractional degrees */ - strcat (GMT->current.plot.format[0][0], "%d"); /* ddd */ + strcat (GMT->current.plot.format[0][0], d_fmt[id]); /* ddd */ if (S->order[1] == GMT_NOTSET && S->n_sec_decimals > 0) { /* ddd.xxx format */ snprintf (fmt, GMT_LEN256, "%%d.%%%d.%dd", S->n_sec_decimals, S->n_sec_decimals); strcat (GMT->current.plot.format[0][1], fmt); } else /* ddd format */ - strcat (GMT->current.plot.format[0][1], "%d"); /* ddd */ + strcat (GMT->current.plot.format[0][1], d_fmt[id]); /* ddd */ if (GMT->current.setting.map_degree_symbol != gmt_none) { /* But we want the degree symbol appended */ snprintf (fmt, GMT_LEN256, "%c", (int)GMT->current.setting.ps_encoding.code[GMT->current.setting.map_degree_symbol]); @@ -7116,8 +7112,8 @@ int gmtlib_plot_C_format (struct GMT_CTRL *GMT) { /* Level 1: degrees and minutes only. index 0 is integer minutes, index 1 is [possibly] fractional minutes */ - strcat (GMT->current.plot.format[1][0], "%d"); /* ddd */ - strcat (GMT->current.plot.format[1][1], "%d"); + strcat (GMT->current.plot.format[1][0], d_fmt[id]); /* ddd */ + strcat (GMT->current.plot.format[1][1], d_fmt[id]); if (GMT->current.setting.map_degree_symbol != gmt_none) { /* We want the degree symbol appended */ sprintf (fmt, "%c", (int)GMT->current.setting.ps_encoding.code[GMT->current.setting.map_degree_symbol]); @@ -7142,8 +7138,8 @@ int gmtlib_plot_C_format (struct GMT_CTRL *GMT) { /* Level 2: degrees, minutes, and seconds. index 0 is integer seconds, index 1 is [possibly] fractional seconds */ - strcat (GMT->current.plot.format[2][0], "%d"); - strcat (GMT->current.plot.format[2][1], "%d"); + strcat (GMT->current.plot.format[2][0], d_fmt[id]); + strcat (GMT->current.plot.format[2][1], d_fmt[id]); if (GMT->current.setting.map_degree_symbol != gmt_none) { /* We want the degree symbol appended */ sprintf (fmt, "%c", (int)GMT->current.setting.ps_encoding.code[GMT->current.setting.map_degree_symbol]); diff --git a/src/gmt_io.h b/src/gmt_io.h index 5e78522a6ca..b1e5d599e3f 100644 --- a/src/gmt_io.h +++ b/src/gmt_io.h @@ -194,7 +194,7 @@ struct GMT_DATE_IO { }; struct GMT_GEO_IO { /* For geographic output and plotting */ - double f_sec_to_int; /* Scale to convert 0.xxx seconds to integer xxx (used for formatting) */ + double f_sec_to_int; /* Scale to convert 0.xxx seconds to integer xxx (used for formatting) */ unsigned int n_sec_decimals; /* Number of digits in decimal seconds (0 for whole seconds) */ unsigned int range; /* 0 for 0/360, 1 for -360/0, 2 for -180/+180 */ int wesn; /* 1 if we want sign encoded with suffix W, E, S, N, 2 if also want space before letter. @@ -202,9 +202,9 @@ struct GMT_GEO_IO { /* For geographic output and plotting */ int order[3]; /* The relative order of degree, minute, seconds in form (-ve if unused) */ bool decimal; /* true if we want to use the FORMAT_FLOAT_OUT for decimal degrees only */ bool no_sign; /* true if we want absolute values (plot only) */ - char x_format[GMT_LEN64]; /* Actual C format used to plot/output longitude */ - char y_format[GMT_LEN64]; /* Actual C format used to plot/output latitude */ - char delimiter[2][2]; /* Delimiter strings in date, e.g. "-" */ + bool leading_zeros; /* True to get leading zeros in degrees */ + char format[GMT_LEN64]; /* Actual C format used to output coordinate */ + char delimiter[2][2]; /* Delimiter strings in date, e.g. "-" */ }; struct GMT_COL_INFO { /* Used by -i and input parsing */ diff --git a/src/gmt_support.c b/src/gmt_support.c index 17305f84a2c..71d44ada979 100644 --- a/src/gmt_support.c +++ b/src/gmt_support.c @@ -15791,7 +15791,7 @@ void gmtlib_get_annot_label (struct GMT_CTRL *GMT, double val, char *label, bool int sign, d, m, s, m_sec; unsigned int k, n_items, level, type; bool zero_fix = false, lat_special = (lonlat == 3), deg_special = (lonlat == 4); - char hemi_pre[GMT_LEN16] = {""}, hemi_post[GMT_LEN16] = {""}, text[GMT_LEN64] = {""}; + char hemi_pre[GMT_LEN16] = {""}, hemi_post[GMT_LEN16] = {""}, text[GMT_LEN64] = {""}, *use_format = NULL; /* Must override do_minutes and/or do_seconds if format uses decimal notation for that item */ @@ -15801,11 +15801,9 @@ void gmtlib_get_annot_label (struct GMT_CTRL *GMT, double val, char *label, bool if (lat_special) lonlat = 1; /* Remove the special flag */ if (deg_special) lonlat = 0; /* Remove the special flag */ - if (lonlat == 0) { /* Fix longitudes range first */ + if (lonlat == 0) /* Fix longitudes range first */ gmt_lon_range_adjust (GMT->current.plot.calclock.geo.range, &val); - } - - if (lonlat) { /* i.e., for geographical data */ + else { /* i.e., for geographical data */ if (doubleAlmostEqual (val, 360.0) && !worldmap) val = 0.0; if (doubleAlmostEqual (val, 360.0) && worldmap && GMT->current.proj.projection_GMT == GMT_OBLIQUE_MERC) @@ -15854,7 +15852,7 @@ void gmtlib_get_annot_label (struct GMT_CTRL *GMT, double val, char *label, bool if (!(lat_special || deg_special) && GMT->current.plot.r_theta_annot && lonlat) /* Special check for the r in r-theta [set via -Jp|P +fe modifier] */ gmt_sprintf_float (GMT, label, GMT->current.setting.format_float_map, val); else if (GMT->current.plot.calclock.geo.decimal) - sprintf (label, GMT->current.plot.calclock.geo.x_format, val, hemi_post); + sprintf (label, GMT->current.plot.calclock.geo.format, val, hemi_post); else { (void) gmtlib_geo_to_dms (val, n_items, GMT->current.plot.calclock.geo.f_sec_to_int, &d, &m, &s, &m_sec); /* Break up into d, m, s, and remainder */ if (d == 0 && sign == -1) { /* Must write out -0 degrees, do so by writing -1 and change 1 to 0 */ @@ -15862,24 +15860,26 @@ void gmtlib_get_annot_label (struct GMT_CTRL *GMT, double val, char *label, bool zero_fix = true; } if (hemi_pre[0]) strcpy (label, hemi_pre); + use_format = (lonlat & 1 ? gmt_strrep (GMT->current.plot.format[level][type], "%3.3d", "%2.2d") :strdup (GMT->current.plot.format[level][type])); + switch (2*level+type) { case 0: - sprintf (text, GMT->current.plot.format[level][type], d, hemi_post); + sprintf (text, use_format, d, hemi_post); break; case 1: - sprintf (text, GMT->current.plot.format[level][type], d, m_sec, hemi_post); + sprintf (text, use_format, d, m_sec, hemi_post); break; case 2: - sprintf (text, GMT->current.plot.format[level][type], d, m, hemi_post); + sprintf (text, use_format, d, m, hemi_post); break; case 3: - sprintf (text, GMT->current.plot.format[level][type], d, m, m_sec, hemi_post); + sprintf (text, use_format, d, m, m_sec, hemi_post); break; case 4: - sprintf (text, GMT->current.plot.format[level][type], d, m, s, hemi_post); + sprintf (text, use_format, d, m, s, hemi_post); break; case 5: - sprintf (text, GMT->current.plot.format[level][type], d, m, s, m_sec, hemi_post); + sprintf (text, use_format, d, m, s, m_sec, hemi_post); break; } if (zero_fix) text[1] = '0'; /* Undo the fix above */