From c06f0b8c1346a76c0e2763af5ea65726f988f851 Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Sat, 29 Aug 2020 13:01:36 -1000 Subject: [PATCH 1/5] Requires special -C +m modifier to report Mercator units relative to standard parallel Normallly, there is no such thing as Mercator should report relative to Equator. However, when you wish to make a Mercator map centered on a point and give spacial distances then we temporarily need to ability to measure Mercator distances from that point. --- src/gmt_init.c | 8 +++++--- src/gmt_proj.c | 4 ++-- src/mapproject.c | 22 +++++++++++++++++++--- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/gmt_init.c b/src/gmt_init.c index b596cd32efd..d08b6ea6e5c 100644 --- a/src/gmt_init.c +++ b/src/gmt_init.c @@ -865,7 +865,7 @@ GMT_LOCAL int gmtinit_rectR_to_geoR (struct GMT_CTRL *GMT, char unit, double rec uint64_t dim[GMT_DIM_SIZE] = {1, 1, 2, 2}; /* Just a single data table with one segment with two 2-column records */ bool was_R, was_J; double wesn[4]; - char buffer[GMT_LEN256] = {""}, Jstring[GMT_LEN128] = {""}, in_string[GMT_VF_LEN] = {""}, out_string[GMT_VF_LEN] = {""}, *v = NULL; + char buffer[GMT_LEN256] = {""}, Jstring[GMT_LEN128] = {""}, in_string[GMT_VF_LEN] = {""}, out_string[GMT_VF_LEN] = {""}, origin_flag[4] = {""}, *v = NULL; struct GMT_DATASET *In = NULL, *Out = NULL; GMT_Report (GMT->parent, GMT_MSG_DEBUG, "Call gmtinit_rectR_to_geoR to convert projected -R to geo -R\n"); @@ -911,6 +911,8 @@ GMT_LOCAL int gmtinit_rectR_to_geoR (struct GMT_CTRL *GMT, char unit, double rec GMT_Report (GMT->parent, GMT_MSG_ERROR, "UTM projection insufficiently specified to auto-determine geographic region\n"); return (GMT_MAP_NO_PROJECTION); } + if (GMT->current.proj.projection_GMT == GMT_MERCATOR) /* Special use of Mercator units relative to stated origin */ + strcpy (origin_flag, "+m"); break; case 2: /* Conical: Use default patch */ break; @@ -948,8 +950,8 @@ GMT_LOCAL int gmtinit_rectR_to_geoR (struct GMT_CTRL *GMT, char unit, double rec v[0] = '\0'; } } - snprintf (buffer, GMT_LEN256, "-R%g/%g/%g/%g -J%s -I -F%c -C -bi2d -bo2d -<%s ->%s --GMT_HISTORY=readonly", - wesn[XLO], wesn[XHI], wesn[YLO], wesn[YHI], Jstring, unit, in_string, out_string); + snprintf (buffer, GMT_LEN256, "-R%g/%g/%g/%g -J%s -I -F%c -C%s -bi2d -bo2d -<%s ->%s --GMT_HISTORY=readonly", + wesn[XLO], wesn[XHI], wesn[YLO], wesn[YHI], Jstring, unit, origin_flag, in_string, out_string); if (get_R) GMT_Report (GMT->parent, GMT_MSG_DEBUG, "Obtaining geographic corner coordinates via mapproject %s\n", buffer); if (GMT_Call_Module (GMT->parent, "mapproject", GMT_MODULE_CMD, buffer) != GMT_OK) /* Get the corners in degrees via mapproject */ return (GMT->parent->error); diff --git a/src/gmt_proj.c b/src/gmt_proj.c index fc26d32253c..095ea2d6229 100644 --- a/src/gmt_proj.c +++ b/src/gmt_proj.c @@ -672,14 +672,14 @@ GMT_LOCAL void gmtproj_merc_sph (struct GMT_CTRL *GMT, double lon, double lat, d if (GMT->current.proj.GMT_convert_latitudes) lat = gmt_M_latg_to_latc (GMT, lat); *x = GMT->current.proj.j_x * D2R * lon; - *y = (fabs (lat) < 90.0) ? GMT->current.proj.j_x * d_log (GMT, tand (45.0 + 0.5 * lat)) - GMT->current.proj.j_yc : copysign (DBL_MAX, lat); + *y = (fabs (lat) < 90.0) ? GMT->current.proj.j_x * d_log (GMT, tand (45.0 + 0.5 * lat)) : copysign (DBL_MAX, lat); } GMT_LOCAL void gmtproj_imerc_sph (struct GMT_CTRL *GMT, double *lon, double *lat, double x, double y) { /* Convert Mercator x/y to lon/lat (GMT->current.proj.EQ_RAD in GMT->current.proj.j_ix) */ *lon = x * GMT->current.proj.j_ix * R2D + GMT->current.proj.central_meridian; - *lat = atand (sinh ((y + GMT->current.proj.j_yc) * GMT->current.proj.j_ix)); + *lat = atand (sinh (y * GMT->current.proj.j_ix)); if (GMT->current.proj.GMT_convert_latitudes) *lat = gmt_M_latc_to_latg (GMT, *lat); } diff --git a/src/mapproject.c b/src/mapproject.c index c54b3938696..795a83b2ba5 100644 --- a/src/mapproject.c +++ b/src/mapproject.c @@ -97,9 +97,10 @@ struct MAPPROJECT_CTRL { /* All control options for this program (except common unsigned int mode; double lon, lat; /* Fixed point of reference */ } A; - struct MAPPROJECT_C { /* -C[/] */ + struct MAPPROJECT_C { /* -C[/][+m] */ bool active; bool shift; + bool m_origin; /* True if we want projected Mercator y-values relative to standard latitude [Equator] */ double easting, northing; /* Shifts */ } C; struct MAPPROJECT_D { /* -D */ @@ -482,12 +483,17 @@ static int parse (struct GMT_CTRL *GMT, struct MAPPROJECT_CTRL *Ctrl, struct GMT break; case 'C': Ctrl->C.active = true; + if (opt->arg[0] && (p = strstr (opt->arg, "+m"))) { /* Gave +m for reset relative offsets to Mercator origin */ + Ctrl->C.m_origin = true; + p[0] = '\0'; /* Temporarily chop off modifier */ + } if (opt->arg[0]) { /* Also gave shifts */ n_errors += gmt_M_check_condition (GMT, sscanf (opt->arg, "%lf/%lf", &Ctrl->C.easting, &Ctrl->C.northing) != 2, "Option -C: Expected -C[/]\n"); Ctrl->C.shift = true; } will_need_RJ = true; /* Since -C is used with projections only */ + if (p) p[0] = '+'; /* Restore modifier */ break; case 'D': Ctrl->D.active = true; @@ -752,6 +758,7 @@ static int parse (struct GMT_CTRL *GMT, struct MAPPROJECT_CTRL *Ctrl, struct GMT n_errors += gmt_M_check_condition (GMT, ((Ctrl->T.active && GMT->current.proj.datum.h_given) || Ctrl->E.active) && GMT->common.b.active[GMT_IN] && gmt_get_cols (GMT, GMT_IN) < 3, "For -E or -T, binary input data (-bi) must have at least 3 columns\n"); + n_errors += gmt_M_check_condition (GMT, Ctrl->C.m_origin && GMT->current.proj.projection_GMT != GMT_MERCATOR, "Option -C: Can only give +m for Mercator projection\n"); if (!(n_errors || GMT->common.R.active[RSET])) { GMT->common.R.wesn[XLO] = 0.0; GMT->common.R.wesn[XHI] = 360.0; @@ -777,7 +784,7 @@ EXTERN_MSC int GMT_mapproject (void *V_API, int mode, void *args) { uint64_t row, n_read_in_seg, seg, n_read = 0, n = 0, k, n_output = 0; double x_in = 0.0, y_in = 0.0, d = 0.0, fwd_scale, inv_scale, xtmp, ytmp, *out = NULL; - double xmin, xmax, ymin, ymax, inch_to_unit, unit_to_inch, u_scale, y_out_min; + double xmin, xmax, ymin, ymax, inch_to_unit, unit_to_inch, u_scale, y_out_min, m_standard_y_value = 0.0; double x_in_min, x_in_max, y_in_min, y_in_max, x_out_min, x_out_max, y_out_max; double xnear = 0.0, ynear = 0.0, lon_prev = 0, lat_prev = 0, **data = NULL, *in = NULL; double speed = 0, last_speed = -1.0, extra[MP_COL_N]; /* Max possible extra output columns from -A -G -L -Z */ @@ -1163,9 +1170,14 @@ EXTERN_MSC int GMT_mapproject (void *V_API, int mode, void *args) { two = (Ctrl->E.active || (Ctrl->T.active && GMT->current.proj.datum.h_given)) ? 3 : 2; /* # of output points from conversion */ if (Ctrl->C.shift && Ctrl->F.active) { /* Use same units in -C and -F */ - Ctrl->C.easting *= u_scale; + Ctrl->C.easting *= u_scale; Ctrl->C.northing *= u_scale; } + if (Ctrl->C.m_origin) { /* Use same units in -C and -F */ + m_standard_y_value = GMT->current.proj.j_yc; /* Special Mercator adjustment for measuring distance relative to standard latitude */ + if (Ctrl->F.active) /* Use same units in -C and -F */ + m_standard_y_value *= fwd_scale; + } if (Ctrl->L.active) { /* Possibly adjust output types */ if (Ctrl->L.mode == GMT_MP_GIVE_FRAC) /* Want fractional point locations */ @@ -1258,6 +1270,8 @@ EXTERN_MSC int GMT_mapproject (void *V_API, int mode, void *args) { in[GMT_X] -= Ctrl->C.easting; in[GMT_Y] -= Ctrl->C.northing; } + if (Ctrl->C.m_origin) /* Special Mercator adjustment for measuring distance relative to standard latitude */ + in[GMT_Y] += m_standard_y_value; if (Ctrl->N.active) { out[GMT_X] = in[GMT_X]; out[GMT_Y] = gmt_lat_swap (GMT, in[GMT_Y], lat_mode); @@ -1366,6 +1380,8 @@ EXTERN_MSC int GMT_mapproject (void *V_API, int mode, void *args) { out[GMT_X] += Ctrl->C.easting; out[GMT_Y] += Ctrl->C.northing; } + else if (Ctrl->C.m_origin) /* Special Mercator adjustment for measuring distance relative to standard latitude */ + out[GMT_Y] -= m_standard_y_value; if (GMT->current.proj.three_D) { double xx = out[GMT_X], yy = out[GMT_Y]; gmt_xyz_to_xy (GMT, xx, yy, gmt_z_to_zz (GMT, in[GMT_Z]), &out[GMT_X], &out[GMT_Y]); From 45af89c07d73e3ec899435e154c93f22e1bfa85c Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Sat, 29 Aug 2020 13:41:48 -1000 Subject: [PATCH 2/5] Document -C+m --- doc/rst/source/mapproject.rst | 8 +++++--- src/mapproject.c | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/rst/source/mapproject.rst b/doc/rst/source/mapproject.rst index 92093c2df4a..3c9c3ccbdce 100644 --- a/doc/rst/source/mapproject.rst +++ b/doc/rst/source/mapproject.rst @@ -15,7 +15,7 @@ Synopsis **gmt mapproject** [ *tables* ] |-J|\ *parameters* |SYN_OPT-R| [ |-A|\ **b**\|\ **B**\|\ **f**\|\ **F**\|\ **o**\|\ **O**\ [*lon0*/*lat0*][**+v**] ] -[ |-C|\ [*dx*/*dy*] ] +[ |-C|\ [*dx*/*dy*][**+m**] ] [ |-D|\ **c**\|\ **i**\|\ **p** ] [ |-E|\ [*datum*] ] [ |-F|\ [*unit*] ] [ |-G|\ [*lon0*/*lat0*][**+a**][**+i**][**+u**\ *unit*][**+v**] ] @@ -105,7 +105,7 @@ Optional Arguments .. _-C: -**-C**\ [*dx*/*dy*] +**-C**\ [*dx*/*dy*][**+m**] Set center of projected coordinates to be at map projection center [Default is lower left corner]. Optionally, add offsets in the projected units to be added (or subtracted when **-I** is set) to @@ -113,7 +113,9 @@ Optional Arguments northings for particular projection zones [0/0]. The unit used for the offsets is the plot distance unit in effect (see :term:`PROJ_LENGTH_UNIT`) unless **-F** is used, in which case the - offsets are in meters. + offsets are in meters. Alternatively, for the Mercator projection + only, append **+m** to set the origin of the projected *y* coordinates + to coincide with the standard parallel [Equator]. .. _-D: diff --git a/src/mapproject.c b/src/mapproject.c index 795a83b2ba5..7429eb67447 100644 --- a/src/mapproject.c +++ b/src/mapproject.c @@ -190,7 +190,7 @@ static int usage (struct GMTAPI_CTRL *API, int level) { const char *name = gmt_show_name_and_purpose (API, THIS_MODULE_LIB, THIS_MODULE_CLASSIC_NAME, THIS_MODULE_PURPOSE); if (level == GMT_MODULE_PURPOSE) return (GMT_NOERROR); GMT_Message (API, GMT_TIME_NONE, "usage: %s %s %s\n", name, GMT_J_OPT, GMT_Rgeo_OPT); - GMT_Message (API, GMT_TIME_NONE, "\t[-Ab|B|f|F|o|O[/][+v]] [-C[]] [-D%s] [-E[]] [-F[]]\n\t[-G[/][+a][+i][+u][+v]]", GMT_DIM_UNITS_DISPLAY); + GMT_Message (API, GMT_TIME_NONE, "\t[-Ab|B|f|F|o|O[/][+v]] [-C[][+m]] [-D%s] [-E[]] [-F[]]\n\t[-G[/][+a][+i][+u][+v]]", GMT_DIM_UNITS_DISPLAY); GMT_Message (API, GMT_TIME_NONE, " [-I] [-L
[+u][+p]] [-N[a|c|g|m]]\n\t[-Q[e|d]] [-S] [-T[h][/] [%s] [-W[g|h|j|n|w|x]] [-Z[][+a][+i][+f][+t]]\n", GMT_V_OPT); GMT_Message (API, GMT_TIME_NONE, "\t[%s] [%s] [%s] [%s]\n\t[%s] [%s]\n\t[%s] [%s] [%s]\n\t[%s]\n\t[%s] [%s] [%s] [%s]\n\n", GMT_b_OPT, GMT_d_OPT, GMT_e_OPT, GMT_f_OPT, GMT_g_OPT, GMT_h_OPT, GMT_i_OPT, GMT_j_OPT, GMT_o_OPT, GMT_p_OPT, GMT_q_OPT, GMT_s_OPT, GMT_colon_OPT, GMT_PAR_OPT); @@ -210,6 +210,7 @@ static int usage (struct GMTAPI_CTRL *API, int level) { GMT_Message (API, GMT_TIME_NONE, "\t-C Return x/y relative to projection center [Default is relative to lower left corner].\n"); GMT_Message (API, GMT_TIME_NONE, "\t Optionally append to add (or subtract if -I) (i.e., false easting & northing) [0/0].\n"); GMT_Message (API, GMT_TIME_NONE, "\t Units are plot units unless -F is set in which case the unit is meters.\n"); + GMT_Message (API, GMT_TIME_NONE, "\t Mercator only: Append +m to set origin for projected y-values to the standard parallel [Equator].\n"); GMT_Message (API, GMT_TIME_NONE, "\t-D Temporarily reset PROJ_LENGTH_UNIT to be c (cm), i (inch), or p (point).\n"); GMT_Message (API, GMT_TIME_NONE, "\t Cannot be used if -F is set.\n"); GMT_Message (API, GMT_TIME_NONE, "\t-E Convert (lon, lat, h) to Earth Centered Earth Fixed (ECEF) coordinates [-I for inverse].\n"); @@ -759,6 +760,7 @@ static int parse (struct GMT_CTRL *GMT, struct MAPPROJECT_CTRL *Ctrl, struct GMT GMT->common.b.active[GMT_IN] && gmt_get_cols (GMT, GMT_IN) < 3, "For -E or -T, binary input data (-bi) must have at least 3 columns\n"); n_errors += gmt_M_check_condition (GMT, Ctrl->C.m_origin && GMT->current.proj.projection_GMT != GMT_MERCATOR, "Option -C: Can only give +m for Mercator projection\n"); + n_errors += gmt_M_check_condition (GMT, Ctrl->C.m_origin && Ctrl->C.northing != 0.0, "Option -C: Cannot mix +m and the \"northing\" setting\n"); if (!(n_errors || GMT->common.R.active[RSET])) { GMT->common.R.wesn[XLO] = 0.0; GMT->common.R.wesn[XHI] = 360.0; From 9b736385f216eb98d7a0ec3c67838e19d0dc41d4 Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Sat, 29 Aug 2020 14:05:33 -1000 Subject: [PATCH 3/5] Update gmt_proj.c --- src/gmt_proj.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/gmt_proj.c b/src/gmt_proj.c index 095ea2d6229..41f977ccad9 100644 --- a/src/gmt_proj.c +++ b/src/gmt_proj.c @@ -655,8 +655,6 @@ GMT_LOCAL void gmtproj_ipolar (struct GMT_CTRL *GMT, double *x, double *y, doubl GMT_LOCAL void gmtproj_vmerc (struct GMT_CTRL *GMT, double lon0, double slat) { /* Set up a Mercator transformation with origin at (lon0, lat0) */ - if (GMT->current.proj.GMT_convert_latitudes) slat = gmt_M_latg_to_latc (GMT, slat); - GMT->current.proj.central_meridian = lon0; GMT->current.proj.j_x = cosd (slat) / d_sqrt (1.0 - GMT->current.proj.ECC2 * sind (slat) * sind (slat)) * GMT->current.proj.EQ_RAD; GMT->current.proj.j_ix = 1.0 / GMT->current.proj.j_x; From f9ac5e7112f531a80bde349d6f5b31c4cfcdab81 Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Sat, 29 Aug 2020 14:16:37 -1000 Subject: [PATCH 4/5] Update gmt_proj.c --- src/gmt_proj.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/gmt_proj.c b/src/gmt_proj.c index 41f977ccad9..66aebc66011 100644 --- a/src/gmt_proj.c +++ b/src/gmt_proj.c @@ -652,13 +652,17 @@ GMT_LOCAL void gmtproj_ipolar (struct GMT_CTRL *GMT, double *x, double *y, doubl /* -JM MERCATOR PROJECTION */ -GMT_LOCAL void gmtproj_vmerc (struct GMT_CTRL *GMT, double lon0, double slat) { +GMT_LOCAL void gmtproj_vmerc (struct GMT_CTRL *GMT, double lon0, double lat0) { /* Set up a Mercator transformation with origin at (lon0, lat0) */ + double aux_lat0 = (GMT->current.proj.GMT_convert_latitudes) ? gmt_M_latg_to_latc (GMT, lat0) : lat0; + GMT->current.proj.central_meridian = lon0; - GMT->current.proj.j_x = cosd (slat) / d_sqrt (1.0 - GMT->current.proj.ECC2 * sind (slat) * sind (slat)) * GMT->current.proj.EQ_RAD; + /* Need geodetic latitude in this expression: */ + GMT->current.proj.j_x = cosd (lat0) / d_sqrt (1.0 - GMT->current.proj.ECC2 * sind (lat0) * sind (lat0)) * GMT->current.proj.EQ_RAD; GMT->current.proj.j_ix = 1.0 / GMT->current.proj.j_x; - GMT->current.proj.j_yc = (fabs (slat) > 0.0) ? GMT->current.proj.j_x * d_log (GMT, tand (45.0 + 0.5 * slat)) : 0.0; + /* Need conformal latitude in this expression (same as in gmtproj_merc_sph) */ + GMT->current.proj.j_yc = (fabs (lat0) > 0.0) ? GMT->current.proj.j_x * d_log (GMT, tand (45.0 + 0.5 * aux_lat0)) : 0.0; } /* Mercator projection for the sphere */ From 36f044d99ae073ec9af12cac4977518de9d8b3aa Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Sat, 29 Aug 2020 14:30:30 -1000 Subject: [PATCH 5/5] Update merc_origin.ps --- test/psbasemap/merc_origin.ps | Bin 23437 -> 23432 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/psbasemap/merc_origin.ps b/test/psbasemap/merc_origin.ps index dd45f6dd324b872db9cb8f49361d4c7a4e936ea5..379452f2b924e86ea048bfe5964da1a568fded49 100644 GIT binary patch delta 2833 zcmb_e%a7Yc99F8Ts)KkGHp#*Y;Yvk)h{mt+t3oQF##7j}x=@B(dt)*|FWS zATTX#bI%#Zexvr=OGh_T9Ql~~?C+PKzn}IgA-fr-DWQp^ zh;5P$2@PTjTZ(-$!1OjO@5Uv*hrKK%lBDeU0ih%b;OIx}*M$ZizX@7}FrCE6ZsR`ux<2NBkfRv81e~eb`@4LY(l$TEXZPi%k#HID*i%eoR5* zCeO^CzP32R1!afEw@I{vp$C2wPI>~L(0*_MOnizOU7~vCA}bl0TW+R zlA@t>+)x_|@JW|FS$J#IrPxaYXjj=Iyyx-YV381k*A*|Lltdnsw422#3_j|GB;WWu zVMw~rO)rDtl0lr7TR}Xq&BxOXL?(DWqvEX+@P~LGKJN7hh4^>@86-t`!}my(H?-^p z)XN6lkbDS1OmUCmVP8^qGAJUgPZhd@lc`!~cf6QO)3xW-kuVH~!e5XVMwTUDUP)Ol zeYcyDgb&S+?{bep_B%vk%EILnt3^NHz8*9&F~@3IGW%&kZjeFV?`kQ#%D!)&WZyPl zINlL5b){3Dl9W!#?69TQ>36rri6sT+bUaO8UWNR)JQGvDOTZmL1QWsRm)6O*>k9ak z*AC)^9XtFOa0fW?vJlAZ_tx=|qy&Nqek?k~{8&7lF`i0R==$6eNfJm(RvgUAGj%1K zI#ZMob7e5W0Or0E!adI#h1_yJSInRLpDq4rwjE2=Ro9U<+iWAvaBWxB<+I3W+ct7l z+csdMwl&+Z9o0724{NV4B2{x8Lv6bVf`&EO>_1t1vDQS6tjbs5bJj8Bi}GfDO}3E3 zo_8884OK$At|7K`b$JDum6&M&Xq%=h!JV~i@aF+Wfe`C7q&Y2K^Y_!pAR!3qOj>CT5xNxD`71C_& zKnk7#nO3z;4l-r4IjVMrTocWa5gy6?HtA~CI3)}wu1w41;Oqo8>r3ESO|Q1eLH5UH zW1zVeAoCKNHb3-DOX&wMP6#%|_t5%v0yr=pa|uTx%XT$7ghPTc5*y!+S{%7_=(ww1OA&g&oMs3wG5lpwi_$(bPnoR zjyqQ;$7ghGr1Gu~!_#2@ZhvqHeiv_CKT-aFcmMj<=)q|@_2gT1agEPvmJJzCX|`VA z{D)XBaihS6=}R0HxbRwun*}bQ{QaJKh`7#x%D2wcML=YM#19cq%mZWG9FGTZ?E(Ab U#@GMn-w*a=?cV-BH@~a>2VaorB>(^b delta 2756 zcmbVO%WfP+6xA3J(X$AOn1_jk(jWu`$?o?n3&JFsg^`o-BX(?y1?BGYOv^pplj`ok zD2gT zm$mQnOE$*3;r;OV*&C{N!&Gl*?rF33&t++CySI+AFxKeVn`g#h9z{5lBn3xNI7-7* zQZj-9JVfLez+r&W0gJ}7m!nXkA6)tN^FLi`KC9K_XK#HyNqt0;xUTfNzz$Hq zk4futBZB-aOkzpt=V6qFaUUEUWsPmtE+z&!bFgJK0 zh>_47)iKEiNuHuOpuaYk-skmgp~yYZE^w1jqhZQpPw2#vw_LaeRn~ zq@42uMJAF&?1kXl7sr(|YUbq$50Z{E+zh@F>Dx zNlGURqkuWPi*2cA5lQw;)0<*ml@T%(E% zyixL2tEE@g>9(q~b$2|kno(z9wFtv-s|FZIf7-frK@L-Mbow`Vvuvwkzyy#7J*z5e z0!W{3H*x(jEARW`-=+9^DT!i;LVb`f=kpXb6n zU&w7w1Lw%P=4tfWPP@tE&qo~HfJjq;=VHvzE&ZYt45ueMH)|IC3pB08b*8Jk5NS@} zxfrtylU)bZZcOoW-e!lh%AFqCb6neS?L}RBvU{n;;qz2a)#zlmslap5o?~j}q71vh z7*5Z2zgRLny7}P!xu0rJ9_&n>UzamqKB)7XZAG)$#(V?^Mc{_x!nIi7hQRs7R^q0> z`6X83mcTj0E;6PMH#6WvA|HHQ=K-FD2UubjnBucG!UF9%eZ2SM|Gel=NBhf5uK+Qu B+Fk$v