%% The LaTeX package mercatormap - version 1.3.1 (2026/06/03) %% mercatormap.sty: geographic coordinates (Mercator projection) and map tiles for TikZ pictures %% %% ------------------------------------------------------------------------------------------- %% Copyright (c) 2020-2026 by Prof. Dr. Dr. Thomas F. Sturm %% ------------------------------------------------------------------------------------------- %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 %% of this license or (at your option) any later version. %% The latest version of this license is in %% http://www.latex-project.org/lppl.txt %% and version 1.3 or later is part of all distributions of LaTeX %% version 2005/12/01 or later. %% %% This work has the LPPL maintenance status `author-maintained'. %% %% This work consists of all files listed in README %% \NeedsTeXFormat{LaTeX2e}[2026-06-01] \ProvidesExplPackage{mercatormap}{2026/06/03}{1.3.1} {A Web Mercator projection package with map tile support} \RequirePackage{ siunitx,graphicx,tikz } \ExplSyntaxOff % space character problem if within explSyntax \usetikzlibrary{shadings} \ExplSyntaxOn %\debug_on:n {all} \ProvideExpandableDocumentCommand \mrcpkgprefix {} {} \NewDocumentCommand\mermapset { m } { \keys_set:nn { mermap } {#1} } \NewDocumentCommand\mermapsetsupply { m } { \keys_set:nn { mermap/supply } {#1} } \NewDocumentCommand\mermapsetmarker { m } { \keys_set:nn { mermap/marker } {#1} } %---- scratch variables -------------------------------------------------------- \box_new:N \l__mermap_tmpa_box \clist_new:N \l__mermap_tmpa_clist \dim_new:N \l__mermap_tmpa_dim \dim_new:N \l__mermap_tmpb_dim \fp_new:N \l__mermap_tmpa_fp \fp_new:N \l__mermap_tmpb_fp \tl_new:N \g__mermap_tmpa_tl \tl_new:N \l__mermap_tmpa_tl \tl_new:N \l__mermap_tmpb_tl %---- constants ---------------------------------------------------------------- \fp_const:Nn \c__mermap_scale_radius_fp { 6371*pi/180 } \fp_const:Nn \c__mermap_mean_radius_fp { 637100000cm } \fp_const:Nn \c__mermap_mile_fp { 1.609344 } \tl_const:Ne \c__mermap_argone_colon_argtwo_tl { #1 \c_colon_str #2 } %---- map definition ----------------------------------------------------------- \dim_new:N \l__mermap_tile_size_dim \fp_new:N \l__mermap_mapeast_fp \fp_new:N \l__mermap_mapnorth_fp \fp_new:N \l__mermap_mapsouth_fp \fp_new:N \l__mermap_mapwest_fp \fp_new:N \l__mermap_tex_height_fp \fp_new:N \l__mermap_tex_width_fp \fp_new:N \l__mermap_tile_northoffset_fp \fp_new:N \l__mermap_tile_southoffset_fp \fp_new:N \l__mermap_tile_westoffset_fp \int_new:N \l__mermap_tile_xmax_int \int_new:N \l__mermap_tile_xmin_int \int_new:N \l__mermap_tile_ymax_int \int_new:N \l__mermap_tile_ymin_int \int_new:N \l__mermap_tile_zoom_int \tl_new:N \l__mermap_attribution_print_tl \tl_new:N \l__mermap_attribution_tl \tl_new:N \l__mermap_pixel_height_tl \tl_new:N \l__mermap_pixel_width_tl \tl_new:N \l__mermap_tile_basename_tl \tl_new:N \l__mermap_tile_resource_tl \keys_define:nn { mermap/mapdef } { west .fp_set:N = \l__mermap_mapwest_fp, east .fp_set:N = \l__mermap_mapeast_fp, north .fp_set:N = \l__mermap_mapnorth_fp, south .fp_set:N = \l__mermap_mapsouth_fp, zoom .int_set:N = \l__mermap_tile_zoom_int, xmin .int_set:N = \l__mermap_tile_xmin_int, ymin .int_set:N = \l__mermap_tile_ymin_int, xmax .int_set:N = \l__mermap_tile_xmax_int, ymax .int_set:N = \l__mermap_tile_ymax_int, pixelwidth .tl_set:N = \l__mermap_pixel_width_tl, pixelheight .tl_set:N = \l__mermap_pixel_height_tl, westoffset .fp_set:N = \l__mermap_tile_westoffset_fp, northoffset .fp_set:N = \l__mermap_tile_northoffset_fp, southoffset .fp_set:N = \l__mermap_tile_southoffset_fp, basename .tl_set:N = \l__mermap_tile_basename_tl, resource .tl_set:N = \l__mermap_tile_resource_tl, attribution .tl_set:N = \l__mermap_attribution_tl, attribution~print .tl_set:N = \l__mermap_attribution_print_tl, tile~size .dim_set:N = \l__mermap_tile_size_dim, } \NewDocumentCommand \mrcdefinemap { m } { \keys_set:nn { mermap/mapdef } { west = 11, east = 13, north = 50, south = 48, zoom = 9, xmin = 271, ymin = 173, xmax = 275, ymax = 177, pixelwidth = 100, pixelheight = 100, westoffset = 0, northoffset = 0, southoffset = 0, basename = tiles/tile, resource = none, attribution =, attribution~print =, #1 } \__mermap_reset: } %---- coordinate system -------------------------------------------------------- \fp_new:N \l__mermap_cs_lat_fp \fp_new:N \l__mermap_cs_lon_fp \fp_new:N \l__mermap_cs_southreference_fp \fp_new:N \l__mermap_cs_x_fp \fp_new:N \l__mermap_cs_xfactor_fp \fp_new:N \l__mermap_cs_y_fp \fp_new:N \l__mermap_cs_yfactor_fp \fp_new:N \l__mermap_result_fp \fp_new:N \l__mermap_scale_denominator_fp \fp_new:N \l__mermap_scale_fp \fp_new:N \l__mermap_vic_dim_fp \fp_new:N \l__mermap_vic_east_fp \fp_new:N \l__mermap_vic_north_fp \fp_new:N \l__mermap_vic_south_fp \fp_new:N \l__mermap_vic_west_fp \fp_new:N \l__mermap_vic_westeast_fp \fp_new:N \l__mermap_westeast_fp \int_new:N \l__mermap_tile_number_int \keys_define:nn { mermap } { vicinity .fp_set:N = \l__mermap_vic_dim_fp } \keys_set:nn { mermap } { vicinity=2cm } \NewExpandableDocumentCommand \mrcmapwest {} { \fp_to_decimal:N \l__mermap_mapwest_fp } \NewExpandableDocumentCommand \mrcmapeast {} { \fp_to_decimal:N \l__mermap_mapeast_fp } \NewExpandableDocumentCommand \mrcmapnorth {} { \fp_to_decimal:N \l__mermap_mapnorth_fp } \NewExpandableDocumentCommand \mrcmapsouth {} { \fp_to_decimal:N \l__mermap_mapsouth_fp } \NewExpandableDocumentCommand \mrcpixelwidth {} { \tl_use:N \l__mermap_pixel_width_tl } \NewExpandableDocumentCommand \mrcpixelheight {} { \tl_use:N \l__mermap_pixel_height_tl } \NewExpandableDocumentCommand \mrctexwidth {} { \fp_to_dim:N \l__mermap_tex_width_fp } \NewExpandableDocumentCommand \mrctexheight {} { \fp_to_dim:N \l__mermap_tex_height_fp } \NewExpandableDocumentCommand \mrcscale {} { \fp_to_decimal:N \l__mermap_scale_fp } \NewExpandableDocumentCommand \mrcmapscaledenominator {} { \fp_to_decimal:N \l__mermap_scale_denominator_fp } \NewDocumentCommand \mrcmapattribution {} { \tl_use:N \l__mermap_attribution_tl } \NewDocumentCommand \mrcmapattributionprint {} { \tl_use:N \l__mermap_attribution_print_tl } \cs_new_protected_nopar:Npn \__mermap_reset: { \int_set:Nn \l__mermap_tile_number_int { \fp_to_int:n { 2^ \l__mermap_tile_zoom_int }} \fp_set:Nn \l__mermap_westeast_fp { \l__mermap_mapeast_fp - \l__mermap_mapwest_fp } \fp_set:Nn \l__mermap_cs_xfactor_fp { \l__mermap_tile_size_dim * \l__mermap_tile_number_int /360 } \fp_set:Nn \l__mermap_cs_yfactor_fp { \l__mermap_tile_size_dim * \l__mermap_tile_number_int /2pi } \fp_set:Nn \l__mermap_cs_southreference_fp { tand( \l__mermap_mapsouth_fp /2+45) } \__mermap_longitude_to_x:n { \l__mermap_mapwest_fp } \__mermap_x_to_longitude:n { \l__mermap_cs_x_fp - \l__mermap_vic_dim_fp } \fp_set_eq:NN \l__mermap_vic_west_fp \l__mermap_cs_lon_fp \__mermap_longitude_to_x:n { \l__mermap_mapeast_fp } \__mermap_x_to_longitude:n { \l__mermap_cs_x_fp + \l__mermap_vic_dim_fp } \fp_set_eq:NN \l__mermap_vic_east_fp \l__mermap_cs_lon_fp \__mermap_latitude_to_y:n { \l__mermap_mapsouth_fp } \__mermap_y_to_latitude:n { \l__mermap_cs_y_fp - \l__mermap_vic_dim_fp } \fp_set_eq:NN \l__mermap_vic_south_fp \l__mermap_cs_lat_fp \__mermap_latitude_to_y:n { \l__mermap_mapnorth_fp } \fp_set_eq:NN \l__mermap_tex_height_fp \l__mermap_cs_y_fp \__mermap_y_to_latitude:n { \l__mermap_cs_y_fp + \l__mermap_vic_dim_fp } \fp_set_eq:NN \l__mermap_vic_north_fp \l__mermap_cs_lat_fp \fp_set:Nn \l__mermap_tex_width_fp { \l__mermap_westeast_fp * \l__mermap_cs_xfactor_fp } \fp_set:Nn \l__mermap_vic_westeast_fp { \l__mermap_vic_east_fp - \l__mermap_vic_west_fp } \__mermap_mean_latitude:NN \l__mermap_mapsouth_fp \l__mermap_mapnorth_fp \fp_set:Nn \l__mermap_scale_denominator_fp { 2* \c__mermap_mean_radius_fp *cosd( \l__mermap_result_fp ) *pi / \l__mermap_tile_number_int / \l__mermap_tile_size_dim } \fp_set:Nn \l__mermap_scale_fp { \l__mermap_scale_denominator_fp / (1cm*100000) } \__mermap_if_inside_picture_environment:T { \node [ rectangle, name = mrcmap, at = { (0,0) }, above~right, line~width = 0mm, inner~sep = 0mm, outer~sep = 0mm, draw = none, fill = none, minimum~width = \mrctexwidth, minimum~height = \mrctexheight ] {} ; } } \cs_new_protected_nopar:Npn \__mermap_mean_latitude:NN #1#2 { \fp_set:Nn \l__mermap_result_fp { 2*atand(sqrt(tand(#1/2+45)*tand(#2/2+45))) - 90 } } \cs_new_protected_nopar:Npn \__mermap_longitude_to_x:n #1 { \fp_set:Nn \l__mermap_tmpa_fp { #1 - \l__mermap_mapwest_fp } \fp_sub:Nn \l__mermap_tmpa_fp { 360*floor( \l__mermap_tmpa_fp /360) } \fp_set:Nn \l__mermap_tmpa_fp { \l__mermap_tmpa_fp > \l__mermap_westeast_fp ? ( \l__mermap_tmpa_fp - \l__mermap_westeast_fp > 360 - \l__mermap_tmpa_fp ? \l__mermap_tmpa_fp - 360 : \l__mermap_tmpa_fp ) : \l__mermap_tmpa_fp } \fp_set:Nn \l__mermap_cs_x_fp { \l__mermap_tmpa_fp * \l__mermap_cs_xfactor_fp } } \cs_new_protected_nopar:Npn \__mermap_latitude_to_y:n #1 { \fp_set:Nn \l__mermap_cs_y_fp { ln( tand((#1)/2+45)/ \l__mermap_cs_southreference_fp ) * \l__mermap_cs_yfactor_fp } } \cs_new_protected_nopar:Npn \__mermap_x_to_longitude:n #1 { \fp_set:Nn \l__mermap_cs_lon_fp { \l__mermap_mapwest_fp + (#1) / \l__mermap_cs_xfactor_fp } } \cs_new_protected_nopar:Npn \__mermap_y_to_latitude:n #1 { \fp_set:Nn \l__mermap_cs_lat_fp { 2*atand( \l__mermap_cs_southreference_fp *exp((#1)/ \l__mermap_cs_yfactor_fp ) ) - 90 } } \cs_new_protected_nopar:Npn \__mermap_pgfpoint:nn #1#2 { \__mermap_latitude_to_y:n {#1} \__mermap_longitude_to_x:n {#2} \pgfpoint{ \fp_to_dim:N \l__mermap_cs_x_fp } { \fp_to_dim:N \l__mermap_cs_y_fp } } \exp_last_unbraced:NNV \cs_new_protected_nopar:Npn \__mermap_pgfpoint:w \c__mermap_argone_colon_argtwo_tl \q_stop { \__mermap_pgfpoint:nn {#1} {#2} } \cs_new_protected_nopar:Npn \__mermap_pgfpoint:n #1 { \__mermap_pgfpoint:w #1 \q_stop } \NewDocumentCommand \mrcpgfpoint { mm } { \__mermap_pgfpoint:nn {#1} {#2} } \keys_define:nn { mermap/cs } { latitude .code:n = \__mermap_latitude_to_y:n {#1}, longitude .code:n = \__mermap_longitude_to_x:n {#1}, lat .code:n = \__mermap_latitude_to_y:n {#1}, lon .code:n = \__mermap_longitude_to_x:n {#1}, } \tikzdeclarecoordinatesystem { __mrc } { \__mermap_pgfpoint:nn #1 } \tikzdeclarecoordinatesystem { mrcq } { \__mermap_pgfpoint:w #1 \q_stop } \tikzdeclarecoordinatesystem { mrc } { \keys_set:nn { mermap/cs } { #1 } \pgfpoint{ \fp_to_dim:N \l__mermap_cs_x_fp } { \fp_to_dim:N \l__mermap_cs_y_fp } } \prg_new_conditional:Npnn \__mermap_if_in_map:nn #1#2 { p, T, F, TF } { \fp_compare:nNnTF { #1 } > { \l__mermap_mapnorth_fp } { \prg_return_false: } { \fp_compare:nNnTF { #1 } < { \l__mermap_mapsouth_fp } { \prg_return_false: } { \fp_set:Nn \l__mermap_tmpa_fp { #2 - \l__mermap_mapwest_fp } \fp_sub:Nn \l__mermap_tmpa_fp { 360*floor( \l__mermap_tmpa_fp /360) } \fp_compare:nNnTF { \l__mermap_tmpa_fp } > { \l__mermap_westeast_fp } { \prg_return_false: } { \fp_set:Nn \l__mermap_cs_x_fp { \l__mermap_tmpa_fp * \l__mermap_cs_xfactor_fp } \__mermap_latitude_to_y:n {#1} \pgfnoderename{ mrclastpos } { mrcpos } \pgfcoordinate{ mrcpos } { \pgfpoint{ \fp_to_dim:N \l__mermap_cs_x_fp } { \fp_to_dim:N \l__mermap_cs_y_fp } } \prg_return_true: } } } } \NewDocumentCommand \ifmrcinmap { mm } { \__mermap_if_in_map:nnTF {#1} {#2} } \prg_new_conditional:Npnn \__mermap_if_in_vicinity:nn #1#2 { p, T, F, TF } { \fp_compare:nNnTF { #1 } > { \l__mermap_vic_north_fp } { \prg_return_false: } { \fp_compare:nNnTF { #1 } < { \l__mermap_vic_south_fp } { \prg_return_false: } { \fp_set:Nn \l__mermap_tmpa_fp { #2 - \l__mermap_vic_west_fp } \fp_sub:Nn \l__mermap_tmpa_fp { 360*floor( \l__mermap_tmpa_fp /360) } \fp_compare:nNnTF { \l__mermap_tmpa_fp } > { \l__mermap_vic_westeast_fp } { \prg_return_false: } { \fp_set:Nn \l__mermap_cs_x_fp { \l__mermap_tmpa_fp * \l__mermap_cs_xfactor_fp - \l__mermap_vic_dim_fp } \__mermap_latitude_to_y:n {#1} \pgfnoderename{ mrclastpos } { mrcpos } \pgfcoordinate{ mrcpos } { \pgfpoint{ \fp_to_dim:N \l__mermap_cs_x_fp } { \fp_to_dim:N \l__mermap_cs_y_fp } } \prg_return_true: } } } } \NewDocumentCommand \ifmrcinvicinity { mm } { \__mermap_if_in_vicinity:nnTF {#1} {#2} } %---- named positions ---------------------------------------------------------- \cs_new_protected_nopar:Npn \__mermap_set_named_position:nnn #1#2#3 { \cs_set_nopar:cpe { __mermap__lat__#1 } { \fp_to_decimal:n {#2} } \cs_set_nopar:cpe { __mermap__lon__#1 } { \fp_to_decimal:n {#3} } } \NewDocumentCommand \mrcNPdef { mmm } { \__mermap_set_named_position:nnn {#1} {#2} {#3} } \NewDocumentCommand \mrcNPfrompoint { mm } { \path (#2); \__mermap_y_to_latitude:n { \pgf@y } \__mermap_x_to_longitude:n { \pgf@x } \__mermap_set_named_position:nnn {#1} { \fp_to_decimal:N \l__mermap_cs_lat_fp } { \fp_to_decimal:N \l__mermap_cs_lon_fp } } \msg_new:nnnn { mercatormap } { np-undefined } { Named~point~'#1'~is~undefined. } { The~named~point~'#1'~is~not~known:~ perhaps~it~is~spelled~incorrectly. } \NewExpandableDocumentCommand \mrcNPlat { m } { \cs_if_exist_use:cF { __mermap__lat__#1 } { 0 } } \NewExpandableDocumentCommand \mrcNPlon { m } { \cs_if_exist_use:cF { __mermap__lon__#1 } { 0 } } \NewExpandableDocumentCommand \mrcNPcs { m } { __mrc~cs \c_colon_str { { \mrcNPlat{#1} } { \mrcNPlon{#1} } } } \prg_new_conditional:Npnn \__mermap_if_NP_exists:n #1 { p, TF } { \cs_if_exist:cTF { __mermap__lat__#1 } { \cs_if_exist:cTF { __mermap__lon__#1 } { \prg_return_true: } { \prg_return_false: } } { \prg_return_false: } } \NewDocumentCommand \ifmrcNPexists { m } { \__mermap_if_NP_exists:nTF { #1 } } \prg_new_conditional:Npnn \__mermap_if_NP_in_map:n #1 { p, TF } { \__mermap_if_NP_exists:nTF { #1 } { \__mermap_if_in_map:nnTF { \mrcNPlat{#1} } { \mrcNPlon{#1} } { \prg_return_true: } { \prg_return_false: } } { \prg_return_false: } } \NewDocumentCommand \ifmrcNPinmap { m } { \__mermap_if_NP_in_map:nTF { #1 } } \prg_new_conditional:Npnn \__mermap_if_NP_in_vicinity:n #1 { p, TF } { \__mermap_if_NP_exists:nTF { #1 } { \__mermap_if_in_vicinity:nnTF { \mrcNPlat{#1} } { \mrcNPlon{#1} } { \prg_return_true: } { \prg_return_false: } } { \prg_return_false: } } \NewDocumentCommand \ifmrcNPinvicinity { m } { \__mermap_if_NP_in_vicinity:nTF { #1 } } %---- map tile download -------------------------------------------------------- \group_begin: \char_set_catcode_space:n {`\ }% noqa: S204 \char_set_catcode_other:n {`\"}% noqa: S204 \tl_const:Nn \c__mermap_supply_call_boundaries_tl {% % noqa: S204 \l__mermap_python_tl\c_space_tl boundaries % noqa: S204 -u "\str_use:N\l__mermap_supply_url_str" % noqa: S204 -at "\str_use:N\l__mermap_supply_attribution_str" % noqa: S204 -atp "\str_use:N\l__mermap_supply_attribution_print_str" % noqa: S204 -f "\l__mermap_supply_basename_tl" % noqa: S204 -z \int_use:N\l__mermap_supply_zoom_int\c_space_tl % noqa: S204 -w \fp_use:N\l__mermap_supply_west_fp\c_space_tl % noqa: S204 -e \fp_use:N\l__mermap_supply_east_fp\c_space_tl % noqa: S204 -n \fp_use:N\l__mermap_supply_north_fp\c_space_tl % noqa: S204 -s \fp_use:N\l__mermap_supply_south_fp\c_space_tl % noqa: S204 -p \l__mermap_supply_pixel_tl\c_space_tl % noqa: S204 -ts \dim_use:N\l__mermap_tile_size_dim\c_space_tl % noqa: S204 -t \l__mermap_supply_target_tl\c_space_tl % noqa: S204 -d "\str_use:N\l__mermap_definition_id_str"% % noqa: S204 } \tl_const:Nn \c__mermap_supply_call_reference_tl {% % noqa: S204 \l__mermap_python_tl\c_space_tl reference % noqa: S204 -u "\str_use:N\l__mermap_supply_url_str" % noqa: S204 -at "\str_use:N\l__mermap_supply_attribution_str" % noqa: S204 -atp "\str_use:N\l__mermap_supply_attribution_print_str" % noqa: S204 -f "\l__mermap_supply_basename_tl" % noqa: S204 -mw \fp_use:N\l__mermap_supply_width_fp\c_space_tl % noqa: S204 -mh \fp_use:N\l__mermap_supply_height_fp\c_space_tl % noqa: S204 -z \int_use:N\l__mermap_supply_zoom_int\c_space_tl % noqa: S204 -lat \fp_use:N\l__mermap_supply_latitude_fp\c_space_tl % noqa: S204 -lon \fp_use:N\l__mermap_supply_longitude_fp\c_space_tl % noqa: S204 -a \l__mermap_supply_align_tl\c_space_tl % noqa: S204 -p \l__mermap_supply_pixel_tl\c_space_tl % noqa: S204 -ts \dim_use:N\l__mermap_tile_size_dim\c_space_tl % noqa: S204 -t \l__mermap_supply_target_tl\c_space_tl % noqa: S204 -d "\str_use:N\l__mermap_definition_id_str"% % noqa: S204 } \tl_const:Nn \c__mermap_supply_call_areafit_tl {% % noqa: S204 \l__mermap_python_tl\c_space_tl areafit % noqa: S204 -u "\str_use:N\l__mermap_supply_url_str" % noqa: S204 -at "\str_use:N\l__mermap_supply_attribution_str" % noqa: S204 -atp "\str_use:N\l__mermap_supply_attribution_print_str" % noqa: S204 -f "\l__mermap_supply_basename_tl" % noqa: S204 -mw \fp_use:N\l__mermap_supply_width_fp\c_space_tl % noqa: S204 -mh \fp_use:N\l__mermap_supply_height_fp\c_space_tl % noqa: S204 -w \fp_use:N\l__mermap_supply_west_fp\c_space_tl % noqa: S204 -e \fp_use:N\l__mermap_supply_east_fp\c_space_tl % noqa: S204 -n \fp_use:N\l__mermap_supply_north_fp\c_space_tl % noqa: S204 -s \fp_use:N\l__mermap_supply_south_fp\c_space_tl % noqa: S204 -a \l__mermap_supply_align_tl\c_space_tl % noqa: S204 -p \l__mermap_supply_pixel_tl\c_space_tl % noqa: S204 -ts \dim_use:N\l__mermap_tile_size_dim\c_space_tl % noqa: S204 -t \l__mermap_supply_target_tl\c_space_tl % noqa: S204 -d "\str_use:N\l__mermap_definition_id_str"% % noqa: S204 } \group_end: \bool_new:N \l__mermap_script_activated_bool \bool_new:N \l__mermap_fail_on_missing_resource_bool \fp_new:N \l__mermap_supply_east_fp \fp_new:N \l__mermap_supply_height_fp \fp_new:N \l__mermap_supply_latitude_fp \fp_new:N \l__mermap_supply_longitude_fp \fp_new:N \l__mermap_supply_north_fp \fp_new:N \l__mermap_supply_south_fp \fp_new:N \l__mermap_supply_west_fp \fp_new:N \l__mermap_supply_width_fp \int_new:N \g__mermap_automap_int \int_new:N \l__mermap_supply_zoom_int \iow_new:N \l__mermap_file_iow \prop_new:N \g__mermap_apikey_prop \prop_new_linked:N \g__mermap_definition_prop \str_new:N \l__mermap_definition_id_str \str_new:N \l__mermap_definition_postfix_str \str_new:N \l__mermap_definition_prefix_str \str_new:N \l__mermap_supply_attribution_print_str \str_new:N \l__mermap_supply_attribution_str \str_new:N \l__mermap_supply_url_str \tl_new:N \l__mermap_last_mdfivesum_tl \tl_new:N \l__mermap_mdfivesum_tl \tl_new:N \l__mermap_python_tl \tl_new:N \l__mermap_supply_align_tl \tl_new:N \l__mermap_supply_basename_tl \tl_new:N \l__mermap_supply_call_tl \tl_new:N \l__mermap_supply_pixel_tl \tl_new:N \l__mermap_supply_target_tl \tl_new:N \l__mermap_supply_type_tl \exp_last_unbraced:NNV \cs_new_nopar:Npn \__mermap_supply_position:w \c__mermap_argone_colon_argtwo_tl \q_stop { \fp_set:Nn \l__mermap_supply_latitude_fp {#1} \fp_set:Nn \l__mermap_supply_longitude_fp {#2} } \msg_new:nnnn { mercatormap } { api-key-undefined } { Api~key~'#1'~is~undefined. } { You~have~to~set~ \token_to_str:N \mrcsetapikey \iow_char:N \{#1 \iow_char:N \} \iow_char:N \{your~key \iow_char:N \}~first. } \cs_new_protected:Npn \__mermap_supply_url_with_api_key:nnn #1#2#3 { \str_set:Nn \l__mermap_supply_url_str {#1} \prop_get:NnNF \g__mermap_apikey_prop {#2} \l__mermap_tmpa_tl { \msg_error:nne { mercatormap } { api-key-undefined } { #2 } } \str_put_right:NV \l__mermap_supply_url_str \l__mermap_tmpa_tl \str_put_right:Nn \l__mermap_supply_url_str {#3} } \cs_new_protected:Npn \__mermap_supply_add_area_clist:N #1 { \clist_map_inline:Nn #1 { \cs_if_exist:cF { __mermap__lat__##1 } { \msg_error:nne { mercatormap } { np-undefined } { ##1 } } \fp_set:Nn \l__mermap_tmpa_fp { \mrcNPlat{##1} } \fp_compare:nNnT \l__mermap_tmpa_fp < \l__mermap_supply_south_fp { \fp_set_eq:NN \l__mermap_supply_south_fp \l__mermap_tmpa_fp } \fp_compare:nNnT \l__mermap_tmpa_fp > \l__mermap_supply_north_fp { \fp_set_eq:NN \l__mermap_supply_north_fp \l__mermap_tmpa_fp } \fp_set:Nn \l__mermap_tmpa_fp { \mrcNPlon{##1} } \fp_compare:nNnT \l__mermap_tmpa_fp < \l__mermap_supply_west_fp { \fp_set_eq:NN \l__mermap_supply_west_fp \l__mermap_tmpa_fp } \fp_compare:nNnT \l__mermap_tmpa_fp > \l__mermap_supply_east_fp { \fp_set_eq:NN \l__mermap_supply_east_fp \l__mermap_tmpa_fp } } } \msg_new:nnn { mercatormap } { input-area-marker } { The~marker~input~file~'#1'~does~not~exist. } \cs_new:Npn \__mermap_supply_add_area_marker_position: { \fp_compare:nNnT { \l__mermap_marker_latitude_fp } < { \l__mermap_supply_south_fp } { \fp_set_eq:NN \l__mermap_supply_south_fp \l__mermap_marker_latitude_fp } \fp_compare:nNnT { \l__mermap_marker_latitude_fp } > { \l__mermap_supply_north_fp } { \fp_set_eq:NN \l__mermap_supply_north_fp \l__mermap_marker_latitude_fp } \fp_compare:nNnT { \l__mermap_marker_longitude_fp } < { \l__mermap_supply_west_fp } { \fp_set_eq:NN \l__mermap_supply_west_fp \l__mermap_marker_longitude_fp } \fp_compare:nNnT { \l__mermap_marker_longitude_fp } > { \l__mermap_supply_east_fp } { \fp_set_eq:NN \l__mermap_supply_east_fp \l__mermap_marker_longitude_fp } } \cs_new_protected:Npn \__mermap_supply_add_area_marker:n #1 { \group_begin: \RenewDocumentCommand \mrcmarker { m } { \keys_set:nn { mermap/marker } { ##1 } \__mermap_supply_add_area_marker_position: } \file_if_exist_input:nF {#1} { \msg_error:nnn { mercatormap } { input-area-marker } { #1 } } \tl_gset:Ne \g__mermap_tmpa_tl { \exp_not:N \fp_set:Nn \exp_not:N \l__mermap_supply_west_fp { \fp_to_decimal:N \l__mermap_supply_west_fp } \exp_not:N \fp_set:Nn \exp_not:N \l__mermap_supply_east_fp { \fp_to_decimal:N \l__mermap_supply_east_fp } \exp_not:N \fp_set:Nn \exp_not:N \l__mermap_supply_south_fp { \fp_to_decimal:N \l__mermap_supply_south_fp } \exp_not:N \fp_set:Nn \exp_not:N \l__mermap_supply_north_fp { \fp_to_decimal:N \l__mermap_supply_north_fp } } \group_insert_after:N \g__mermap_tmpa_tl \group_end: } \keys_define:nn { mermap/supply } { zoom .int_set:N = \l__mermap_supply_zoom_int, west .fp_set:N = \l__mermap_supply_west_fp, east .fp_set:N = \l__mermap_supply_east_fp, north .fp_set:N = \l__mermap_supply_north_fp, south .fp_set:N = \l__mermap_supply_south_fp, latitude .fp_set:N = \l__mermap_supply_latitude_fp, longitude .fp_set:N = \l__mermap_supply_longitude_fp, position .code:n = { \__mermap_supply_position:w #1 \q_stop }, named~position .meta:nn = { mermap/supply } { latitude = \mrcNPlat{#1}, longitude = \mrcNPlon{#1} }, width .fp_set:N = \l__mermap_supply_width_fp, height .fp_set:N = \l__mermap_supply_height_fp, align .tl_set:N = \l__mermap_supply_align_tl, url .code:n = \str_set:Nn \l__mermap_supply_url_str {#1}, url~with~api~key .code:n = { \__mermap_supply_url_with_api_key:nnn #1 }, basename .tl_set:N = \l__mermap_supply_basename_tl, type .tl_set:N = \l__mermap_supply_type_tl, target .tl_set:N = \l__mermap_supply_target_tl, pixel .tl_set:N = \l__mermap_supply_pixel_tl, attribution .code:n = { \str_set:Nn \l__mermap_supply_attribution_str {#1} \tl_set_rescan:Nnn \l__mermap_attribution_tl {} {#1} }, attribution~print .code:n = { \str_set:Nn \l__mermap_supply_attribution_print_str {#1} \tl_set_rescan:Nnn \l__mermap_attribution_print_tl {} {#1} }, dpi .code:n = { \tl_set:Ne \l__mermap_supply_pixel_tl { \fp_to_int:n { round(#1 * \l__mermap_tile_size_dim / 1in) } } }, tex~width .code:n = { \fp_set:Nn \l__mermap_supply_width_fp { #1 / \l__mermap_tile_size_dim } }, tex~height .code:n = { \fp_set:Nn \l__mermap_supply_height_fp { #1 / \l__mermap_tile_size_dim } }, source .code:n = { \exp_args:Nne \keys_set:nn { mermap/supply } { _source = #1 } }, source .value_required:n = true, _source .choice:, area .code:n = { \clist_set:Nn \l__mermap_tmpa_clist { #1 } \fp_set:Nn \l__mermap_supply_west_fp { inf } \fp_set:Nn \l__mermap_supply_east_fp { -inf } \fp_set:Nn \l__mermap_supply_south_fp { 89 } \fp_set:Nn \l__mermap_supply_north_fp { -89 } \__mermap_supply_add_area_clist:N \l__mermap_tmpa_clist }, area .value_required:n = true, add~area .code:n = { \clist_set:Nn \l__mermap_tmpa_clist { #1 } \__mermap_supply_add_area_clist:N \l__mermap_tmpa_clist }, area~from~marker~input .code:n = { \fp_set:Nn \l__mermap_supply_west_fp { inf } \fp_set:Nn \l__mermap_supply_east_fp { -inf } \fp_set:Nn \l__mermap_supply_south_fp { 89 } \fp_set:Nn \l__mermap_supply_north_fp { -89 } \__mermap_supply_add_area_marker:n { #1 } }, area~from~marker~input .value_required:n = true, add~area~from~marker~input .code:n = { \__mermap_supply_add_area_marker:n { #1 } }, flex~reference~scale .code:n = { \__mermap_set_flex_scale:nn {#1} { \l__mermap_supply_latitude_fp } }, flex~reference~scale .value_required:n = true, area~to~reference .code:n = { \fp_set:Nn \l__mermap_supply_longitude_fp { ( \l__mermap_supply_west_fp + \l__mermap_supply_east_fp )/2 } \__mermap_mean_latitude:NN \l__mermap_supply_north_fp \l__mermap_supply_south_fp \fp_set_eq:NN \l__mermap_supply_latitude_fp \l__mermap_result_fp }, area~to~reference .value_forbidden:n = true, flex~area~scale .meta:nn = { mermap/supply } { area~to~reference, flex~reference~scale = {#1} }, flex~area~scale .value_required:n = true, flex~area~fit .code:n = { \fp_compare:nNnF \l__mermap_tile_size_dim = \l__mermap_flex_tile_size_dim { \fp_set:Nn \l__mermap_tmpa_fp { \l__mermap_tile_size_dim / \l__mermap_flex_tile_size_dim } \fp_set:Nn \l__mermap_supply_width_fp { \l__mermap_supply_width_fp * \l__mermap_tmpa_fp } \fp_set:Nn \l__mermap_supply_height_fp { \l__mermap_supply_height_fp * \l__mermap_tmpa_fp } } \fp_set:Nn \l__mermap_supply_width_fp { \l__mermap_supply_width_fp -(#1)/ \l__mermap_flex_tile_size_dim } \fp_set:Nn \l__mermap_supply_height_fp { \l__mermap_supply_height_fp -(#1)/ \l__mermap_flex_tile_size_dim } \fp_set:Nn \l__mermap_tmpa_fp { min ( 180* \l__mermap_supply_width_fp / ( \l__mermap_supply_east_fp - \l__mermap_supply_west_fp ), pi* \l__mermap_supply_height_fp / ln( tand( \l__mermap_supply_north_fp /2+45) / tand( \l__mermap_supply_south_fp /2 + 45) ) ) } \fp_set:Nn \l__mermap_tmpb_fp { ln( \l__mermap_tmpa_fp )/ln(2) } \fp_set:Nn \l__mermap_tmpb_fp { round( \l__mermap_tmpb_fp )/ \l__mermap_tmpb_fp } \fp_set:Nn \l__mermap_tmpb_fp { \l__mermap_tmpa_fp ^( \l__mermap_tmpb_fp - 1 + 0.0000001) } \dim_set:Nn \l__mermap_tile_size_dim { \fp_to_dim:n { \l__mermap_flex_tile_size_dim / \l__mermap_tmpb_fp }} \fp_set:Nn \l__mermap_supply_width_fp { \l__mermap_supply_width_fp * \l__mermap_tmpb_fp + (#1)/ \l__mermap_tile_size_dim } \fp_set:Nn \l__mermap_supply_height_fp { \l__mermap_supply_height_fp * \l__mermap_tmpb_fp + (#1)/ \l__mermap_tile_size_dim } }, flex~area~fit .default:n = 0pt, } \keys_set:nn { mermap/supply } { zoom = 9, north = 50, south = 48, west = 11, east = 13, latitude = 49, longitude = 12, width = 4, height = 4, align = center, basename = tiles/tile, url =, type = reference, pixel = 256, target = tiles, attribution =, attribution~print =, } \keys_define:nn { mermap } { definition~prefix .code:n = \str_set:Nn \l__mermap_definition_prefix_str {#1}, fail~on~missing~resource .bool_set:N = \l__mermap_fail_on_missing_resource_bool, python .code:n = { \tl_set:Ne \l__mermap_python_tl { #1 ~maptiles.texpy } }, } \keys_set:nn { mermap } { definition~prefix = maps/, fail~on~missing~resource = true, python = python, } \msg_new:nnn { mercatormap } { python-script } { Python~script~'maptiles.texpy'~is~created~for~map~tile~download. } \NewDocumentCommand \mrcactivatescript {} { \msg_info:nn { mercatormap } { python-script } \file_input:n { \mrcpkgprefix mercatorpy.def } \bool_set_true:N \l__mermap_script_activated_bool } \@onlypreamble\mrcactivatescript \NewDocumentCommand \mrcsetapikey { mm } { \prop_gput:Nnn \g__mermap_apikey_prop {#1} {#2} } \cs_new_protected:Npn \__mermap_create_definition_id:n #1 { \tl_set:Ne \l__mermap_tmpa_tl {#1} \tl_trim_spaces:N \l__mermap_tmpa_tl \str_set:Ne \l__mermap_definition_postfix_str { \tl_to_str:N \l__mermap_tmpa_tl } \str_concat:NNN \l__mermap_definition_id_str \l__mermap_definition_prefix_str \l__mermap_definition_postfix_str } \cs_new_protected:Npn \__mermap_map:nn #1#2 { \tl_set:Ne \l__mermap_tmpa_tl {#2} \tl_trim_spaces:N \l__mermap_tmpa_tl \tl_if_empty:NT \l__mermap_tmpa_tl { \int_gincr:N \g__mermap_automap_int \tl_set:Ne \l__mermap_tmpa_tl { automap- \int_compare:nNnTF { \g__mermap_automap_int } < { 10 } { 000 } { \int_compare:nNnTF { \g__mermap_automap_int } < { 100 } { 00 } { \int_compare:nNnT { \g__mermap_automap_int } < { 1000 } { 0 } } } \int_use:N \g__mermap_automap_int } } \exp_args:NV \__mermap_create_definition_id:n \l__mermap_tmpa_tl \__mermap_supplymap:n {#1} \__mermap_applymap: } \NewDocumentCommand \mrcmap { O {} m } { \__mermap_map:nn {#1} {#2} } \msg_new:nnn { mercatormap } { definition-id-used } { Map~definition~'#1'~already~existing } \cs_new_protected:Npn \__mermap_supplymap:n #1 { \group_begin: \keys_set:nn { mermap/supply } { #1 } \prop_if_in:NVT \g__mermap_definition_prop \l__mermap_definition_id_str { \msg_warning:nne { mercatormap } { definition-id-used } { \str_use:N \l__mermap_definition_id_str } } \prop_gput:NVn \g__mermap_definition_prop \l__mermap_definition_id_str {} \bool_if:NT \l__mermap_script_activated_bool { \__mermap_supplymap_call: } \group_end: } \NewDocumentCommand \mrcsupplymap { O {} m } { \__mermap_create_definition_id:n {#2} \__mermap_supplymap:n {#1} } \msg_new:nnnn { mercatormap } { shell-escape } { You~must~invoke~LaTeX~with~the~--shell-escape~flag~to~produce~map~'#1'. } { The~--shell-escape~flag~is~needed,~because~a~Python~sript~has~to~be~called;~see~package~documentation. } \msg_new:nnnn { mercatormap } { target-resource } { Target~and~produced~resource~are~different~for~map~'#1'. } { Your~target~was~' \l__mermap_supply_target_tl '.\\ The~produced~resource~is~' \l__mermap_tile_resource_tl '.\\ Check,~if~' \l__mermap_supply_target_tl '~is~available~via~' \str_use:N \l__mermap_supply_url_str ' \\ or~if~the~zoom~value~is~too~large. } \msg_new:nnnn { mercatormap } { definition-production } { Map~definition~file~not~produced~for~map~'#1'. } { **~The~failed~shell~command~was:\\ \l__mermap_supply_call_tl\\ **~Python~setup~correct? } \cs_new_protected:Npn \__mermap_supplymap_call: { \exp_args:NNc \tl_set:Ne \l__mermap_supply_call_tl { c__mermap_supply_call_ \l__mermap_supply_type_tl _tl } \tl_set:Ne \l__mermap_mdfivesum_tl { \str_mdfive_hash:e { \l__mermap_supply_call_tl } } \file_if_exist:nTF { \l__mermap_definition_id_str .def } { \tl_clear:N \l__mermap_last_mdfivesum_tl \file_if_exist_input:n { \l__mermap_definition_id_str .md5 } \str_if_eq:VVF \l__mermap_mdfivesum_tl \l__mermap_last_mdfivesum_tl { \__mermap_supplymap_call_shell: } } { \__mermap_supplymap_call_shell: } } \cs_new_protected:Npn \__mermap_supplymap_call_shell: { \sys_if_shell_unrestricted:TF { \file_if_exist:nT { \l__mermap_definition_id_str .def } { \iow_open:Nn \l__mermap_file_iow { \l__mermap_definition_id_str .def } \iow_now:Ne \l__mermap_file_iow { \c_backslash_str def \c_backslash_str mrcdefinemap {} \c_percent_str } \iow_close:N \l__mermap_file_iow } \sys_shell_now:e { \l__mermap_supply_call_tl } \file_if_exist:nTF { \l__mermap_definition_id_str .def } { \file_input:n { \l__mermap_definition_id_str .def } \str_if_eq:VVTF \l__mermap_supply_target_tl \l__mermap_tile_resource_tl { \__mermap_write_mdfive:n { \l__mermap_mdfivesum_tl } } { \__mermap_write_mdfive:n { false } \bool_if:NTF \l__mermap_fail_on_missing_resource_bool { \msg_error:nne { mercatormap } { target-resource } { \l__mermap_definition_id_str } } { \msg_warning:nne { mercatormap } { target-resource } { \l__mermap_definition_id_str } } } } { \msg_error:nne { mercatormap } { definition-production } { \l__mermap_definition_id_str } } } { \msg_error:nne { mercatormap } { shell-escape } { \l__mermap_definition_id_str } } } \NewDocumentCommand \mermaplastfivesum { m } { \tl_set:Ne \l__mermap_last_mdfivesum_tl { #1 } } \cs_new_protected:Npn \__mermap_write_mdfive:n #1 { \iow_open:Nn \l__mermap_file_iow { \l__mermap_definition_id_str .md5 } \iow_now:Ne \l__mermap_file_iow { \c_backslash_str mermaplastfivesum {#1} \c_percent_str } \iow_close:N \l__mermap_file_iow } %---- map drawing -------------------------------------------------------------- \dim_new:N \l__mermap_flex_tile_size_dim \dim_new:N \l__mermap_tx_dim \dim_new:N \l__mermap_ty_dim \int_new:N \l__mermap_tile_x_int \int_new:N \l__mermap_tile_xmod_int \int_new:N \l__mermap_tile_y_int \tl_new:N \l__mermap_draw_map_tl \tl_new:N \l__mermap_tikz_map_clip_tl \tl_new:N \l__mermap_tile_filename_tl \prg_new_conditional:Npnn \__mermap_if_inside_picture_environment: { p, TF, T } { \cs_if_exist:NTF \pgfpictureid { \prg_return_true: } { \prg_return_false: } } \cs_new_protected_nopar:Npn \__mermap_set_flex_scale:nn #1#2 { \fp_set:Nn \l__mermap_tmpa_fp { 1+ln( \c__mermap_mean_radius_fp /#1*cosd(#2)*pi/ \l__mermap_flex_tile_size_dim )/ln(2) } \keys_set:nn { mermap } { flex~zoom = \l__mermap_tmpa_fp } } \exp_last_unbraced:NNV \cs_new_protected_nopar:Npn \__mermap_set_flex_scale:w \c__mermap_argone_colon_argtwo_tl \q_stop { \__mermap_set_flex_scale:nn {#1} {#2} } \exp_last_unbraced:NNV \cs_new_protected_nopar:Npn \__mermap_set_named_flex_scale:w \c__mermap_argone_colon_argtwo_tl \q_stop { \__mermap_set_flex_scale:nn {#1} { \mrcNPlat{#2} } } \keys_define:nn { mermap } { tile~size .dim_set:N = \l__mermap_tile_size_dim, flex~tile~size .dim_set:N = \l__mermap_flex_tile_size_dim, flex~zoom .code:n = { \int_set:Nn \l__mermap_supply_zoom_int { \fp_to_int:n { round(#1) } } \dim_set:Nn \l__mermap_tile_size_dim { \fp_to_dim:n { \l__mermap_flex_tile_size_dim *2^(#1 - \l__mermap_supply_zoom_int ) } } }, flex~scale .code:n = { \__mermap_set_flex_scale:w #1 \q_stop }, named~flex~scale .code:n = { \__mermap_set_named_flex_scale:w #1 \q_stop }, map~clip .tl_set:N = \l__mermap_tikz_map_clip_tl, map~scope .code:n = \tikzset{ mermap_scope_style/.style = {#1} }, map~path .code:n = \tikzset{ mermap_path_style/.style = {#1} }, draw .tl_set:N = \l__mermap_draw_map_tl, } \keys_set:nn { mermap } { tile~size = 32.512mm, flex~tile~size = 32.512mm, map~clip = \mrcclipmap, draw = auto, map~scope = , map~path = { upper~left = green!50, upper~right = green!25, lower~left = green!50!black!50, lower~right = green!25 }, } \NewDocumentCommand \mrcclipmap {} { \path[clip] (mrcmap.south~west) rectangle (mrcmap.north~east); } \NewDocumentCommand \mrcboundmap {} { \path[use~as~bounding~box] (mrcmap.south~west) rectangle (mrcmap.north~east); } \cs_new_nopar:Npn \__mermap_drawmap_path: { \begin{ scope } [ xshift = \fp_to_dim:n { (0.5 - \l__mermap_tile_westoffset_fp )* \l__mermap_tile_size_dim }, yshift = \fp_to_dim:n { (0.5 - \l__mermap_tile_southoffset_fp )* \l__mermap_tile_size_dim }, mermap_scope_style ] \tl_use:N \l__mermap_tikz_map_clip_tl \path[mermap_path_style] (mrcmap.south~west) rectangle (mrcmap.north~east); \end{ scope } } \cs_new_protected_nopar:Npn \__mermap_drawtile: { \tl_set:Ne \l__mermap_tile_filename_tl { \exp_not:o \l__mermap_tile_basename_tl _ \int_use:N \l__mermap_tile_zoom_int _ \int_use:N \l__mermap_tile_xmod_int _ \int_use:N \l__mermap_tile_y_int .png } \file_if_exist:nTF { \l__mermap_tile_filename_tl } { \node[line~width=0mm,inner~sep=0mm,outer~sep=0mm,draw=none,fill=none,rectangle] at ( \l__mermap_tx_dim, \l__mermap_ty_dim ) { \includegraphics [ width = \l__mermap_tile_size_dim ] { \l__mermap_tile_filename_tl } } ; } { \path [ mermap_path_style ] ( \l__mermap_tx_dim, \l__mermap_ty_dim ) ++ ( - \l__mermap_tile_size_dim /2, - \l__mermap_tile_size_dim /2) rectangle +( \l__mermap_tile_size_dim, \l__mermap_tile_size_dim ); } } \cs_new_protected_nopar:Npn \__mermap_drawmap_tiles: { \begin{ scope } [ xshift = \fp_to_dim:n { (0.5 - \l__mermap_tile_westoffset_fp )* \l__mermap_tile_size_dim }, yshift = \fp_to_dim:n { (0.5 - \l__mermap_tile_southoffset_fp )* \l__mermap_tile_size_dim }, mermap_scope_style ] \tl_use:N \l__mermap_tikz_map_clip_tl \int_set_eq:NN \l__mermap_tile_x_int \l__mermap_tile_xmin_int \dim_set:Nn \l__mermap_tx_dim { 0pt } \int_until_do:nNnn { \l__mermap_tile_x_int } > { \l__mermap_tile_xmax_int } { \dim_set:Nn \l__mermap_ty_dim { 0pt } \int_set:Nn \l__mermap_tile_xmod_int { \int_mod:nn { \l__mermap_tile_x_int } { \l__mermap_tile_number_int } } \int_compare:nNnT { \l__mermap_tile_xmod_int } < { 0 } { \int_add:Nn \l__mermap_tile_xmod_int { \l__mermap_tile_number_int } } \int_set_eq:NN \l__mermap_tile_y_int \l__mermap_tile_ymax_int \int_until_do:nNnn { \l__mermap_tile_y_int } < { \l__mermap_tile_ymin_int } { \int_compare:nNnF { \l__mermap_tile_y_int } < { 0 } { \int_compare:nNnT { \l__mermap_tile_y_int } < { \l__mermap_tile_number_int } { \__mermap_drawtile: } } \dim_add:Nn \l__mermap_ty_dim { \l__mermap_tile_size_dim } \int_decr:N \l__mermap_tile_y_int } \dim_add:Nn \l__mermap_tx_dim \l__mermap_tile_size_dim \int_incr:N \l__mermap_tile_x_int } \end{ scope } } \cs_new_nopar:Npn \__mermap_drawsinglemap: { \begin{ scope } [ mermap_scope_style ] \tl_use:N \l__mermap_tikz_map_clip_tl \node [ above~right,line~width=0mm,inner~sep=0mm,outer~sep=0mm,draw=none,fill=none,rectangle ] at (0,0) { \includegraphics[width=\mrctexwidth,height=\mrctexheight] { \l__mermap_definition_id_str .png } } ; \end{ scope } } \cs_new_nopar:Npn \__mermap_drawmap_mergedmap: { \str_if_eq:VnTF \l__mermap_tile_resource_tl { mergedmap } { \__mermap_drawsinglemap: } { \__mermap_drawmap_path: } } \cs_new_nopar:Npn \__mermap_drawmap_wmsmap: { \str_if_eq:VnTF \l__mermap_tile_resource_tl { wmsmap } { \__mermap_drawsinglemap: } { \__mermap_drawmap_path: } } \cs_new_nopar:Npn \__mermap_drawmap_auto: { \cs_if_exist:cTF { __mermap_drawmap_ \l__mermap_tile_resource_tl : } { \use:c { __mermap_drawmap_ \l__mermap_tile_resource_tl : } } { \str_if_eq:VnTF \l__mermap_tile_resource_tl { none } { \__mermap_drawmap_path: } { \msg_warning:nne { mercatormap } { draw-undefined } { \tl_use:N \l__mermap_tile_resource_tl } } } } \msg_new:nnnn { mercatormap } { draw-undefined } { 'draw=#1'~is~undefined. } { The~option~value~'#1'~is~not~known~for~'draw': perhaps~it~is~spelled~incorrectly. } \NewDocumentCommand \mrcdrawmap { o } { \group_begin: \IfNoValueF {#1} { \keys_set:nn { mermap } {#1} } \cs_if_exist:cTF { __mermap_drawmap_ \l__mermap_draw_map_tl : } { \use:c { __mermap_drawmap_ \l__mermap_draw_map_tl : } } { \msg_warning:nne { mercatormap } { draw-undefined } { \tl_use:N \l__mermap_draw_map_tl } } \group_end: } \cs_new_protected_nopar:Npn \__mermap_applymap: { \file_input:n { \l__mermap_definition_id_str .def } } \NewDocumentCommand \mrcapplymap { m } { \__mermap_create_definition_id:n {#1} \__mermap_applymap: } \cs_new_protected_nopar:Npn \__mermap_drawinfo: { \begin{ scope } [ every~node/.style = { fill=white,fill~opacity=0.8,text~opacity=1,font=\sffamily\footnotesize } ] \mrcclipmap \tl_set:Nn \l__mermap_tile_basename_tl { _dummy_ } % not existing file \mermapset{ map~path = { draw=white,double=red } } \tikzset{ mermap_path_style/.style = { draw=white,double=red } } \__mermap_drawmap_tiles: \node at (mrcmap.center) { \begin{ tabular } { ll } scale & ca.~\mrcprettymapscale\\ resolution & ca.~\mrcprettymapresolution\\ \TeX\nobreakspace tile~size & ca.~\mrcprettytilesize\\ width & ca.~\mrcprettymapwidth\\ height & ca.~\mrcprettymapheight\\ zoom & $z = \int_use:N \l__mermap_tile_zoom_int $\\ horizontal & $x\in\{ \int_use:N \l__mermap_tile_xmin_int, \ldots, \int_use:N \l__mermap_tile_xmax_int \}$\\ vertical & $y\in\{ \int_use:N \l__mermap_tile_ymin_int, \ldots, \int_use:N \l__mermap_tile_ymax_int \}$ \end{ tabular } } ; \node[above] at (mrcmap.south) { \mrcformlat[format~angle=decimal-4] { \mrcmapsouth }, \SI[round-mode=figures,round-precision=6,detect-all] { \fp_to_decimal:n { \c__mermap_scale_radius_fp * ( \mrcmapeast - \mrcmapwest )*cosd( \mrcmapsouth ) }} { km } } ; \node[below] at (mrcmap.north) { \mrcformlat[format~angle=decimal-4] { \mrcmapnorth }, \SI[round-mode=figures,round-precision=6,detect-all] { \fp_to_decimal:n { \c__mermap_scale_radius_fp * ( \mrcmapeast - \mrcmapwest )*cosd( \mrcmapnorth ) } } { km } } ; \node[rotate=90] at ([xshift=3mm]mrcmap.west) { \mrcformlon[format~angle=decimal-4] { \mrcmapwest }, \SI[round-mode=figures,round-precision=6,detect-all] { \fp_to_decimal:n { \c__mermap_scale_radius_fp * ( \mrcmapnorth - \mrcmapsouth ) } } { km } } ; \node[rotate=90] at ([xshift=-3mm]mrcmap.east) { \mrcformlon[format~angle=decimal-4] { \mrcmapeast }, \SI[round-mode=figures,round-precision=6,detect-all] { \fp_to_decimal:n { \c__mermap_scale_radius_fp * ( \mrcmapnorth - \mrcmapsouth ) } } { km } } ; \end{ scope } } \NewDocumentCommand \mrcdrawinfo { } { \__mermap_drawinfo: } %---- geodetic network --------------------------------------------------------- \dim_new:N \l__mermap_network_distance_dim \int_new:N \l__mermap_network_pieces_int \tl_new:N \l__mermap_network_font_tl \keys_define:nn { mermap } { network~distance .dim_set:N = \l__mermap_network_distance_dim, network~pieces .int_set:N = \l__mermap_network_pieces_int, network~font .tl_set:N = \l__mermap_network_font_tl, } \keys_set:nn { mermap } { network~pieces = 8, network~distance = 2cm, network~font = \fontsize { 4pt } { 4pt } \sffamily, } \cs_new_protected_nopar:Npn \__mermap_compute_network_step:nn #1#2 { \fp_set:Nn \l__mermap_tmpa_fp { min ( \l__mermap_network_pieces_int, round((#1)/ \l__mermap_network_distance_dim ) ) } \fp_set:Nn \l__mermap_tmpb_fp { (#2)/ \l__mermap_tmpa_fp } \fp_set:Nn \l__mermap_tmpa_fp { floor(ln( \l__mermap_tmpb_fp )/ln(10)) } \fp_compare:nNnTF { \l__mermap_tmpa_fp } < { 0 } { \fp_compare:nNnTF { \l__mermap_tmpa_fp } > { -5 } { \exp_args:Nne \keys_set:nn { mermap } { format~angle = decimal \fp_to_int:N \l__mermap_tmpa_fp } } { \keys_set:nn { mermap } { format~angle=decimal } } } { \keys_set:nn { mermap } { format~angle=decimal-0 } } \fp_set:Nn \l__mermap_tmpa_fp { 10^ \l__mermap_tmpa_fp } \fp_set:Nn \l__mermap_tmpb_fp { \l__mermap_tmpb_fp / \l__mermap_tmpa_fp } \fp_compare:nNnTF { abs( \l__mermap_tmpb_fp - 1) } < { abs( \l__mermap_tmpb_fp - 2 ) } { \fp_compare:nNnTF { abs( \l__mermap_tmpb_fp - 1 ) } < { abs( \l__mermap_tmpb_fp - 5 ) } { \fp_set:Nn \l__mermap_result_fp { \l__mermap_tmpa_fp } } { \fp_set:Nn \l__mermap_result_fp { 5* \l__mermap_tmpa_fp } } } { \fp_compare:nNnTF { abs( \l__mermap_tmpb_fp - 2 ) } < { abs( \l__mermap_tmpb_fp - 5 ) } { \fp_set:Nn \l__mermap_result_fp { 2* \l__mermap_tmpa_fp } } { \fp_set:Nn \l__mermap_result_fp { 5* \l__mermap_tmpa_fp } } } } \NewDocumentCommand \mrcdrawnetwork { o } { \begin{ scope } [ every~node/.style = { inner~sep=0.5pt,black!50!gray, font = \l__mermap_network_font_tl, fill=white,opacity=0.3,text~opacity=1 } ] \IfNoValueF {#1} { \keys_set:nn { mermap } {#1} } \tl_use:N \l__mermap_tikz_map_clip_tl \__mermap_compute_network_step:nn { \l__mermap_tex_height_fp } { \l__mermap_mapnorth_fp - \l__mermap_mapsouth_fp } \fp_set:Nn \l__mermap_tmpa_fp { ceil( \l__mermap_mapsouth_fp / \l__mermap_result_fp )* \l__mermap_result_fp } \fp_compare:nNnT { \l__mermap_tmpa_fp - \l__mermap_mapsouth_fp } < { 1e-10 } { \fp_add:Nn \l__mermap_tmpa_fp { \l__mermap_result_fp } } \fp_while_do:nNnn { \l__mermap_tmpa_fp } < { \l__mermap_mapnorth_fp } { \tl_set:Nn \l__mermap_tmpa_tl { \fp_use:N \l__mermap_tmpa_fp } \draw[gray,very~thin] ( mrc~cs \c_colon_str lat = \l__mermap_tmpa_tl, lon = \mrcmapwest ) coordinate (mermap_temp) node [ right=1mm,inner~sep=0.5pt,black!50!gray, font = \l__mermap_network_font_tl, fill=white,opacity=0.3,text~opacity=1, ] { \mrcformlat { \l__mermap_tmpa_tl } } -- (mermap_temp -| mrcmap.east) node [ left=1mm,inner~sep=0.5pt,black!50!gray, font = \l__mermap_network_font_tl, fill=white,opacity=0.3,text~opacity=1, ] { \mrcformlat { \l__mermap_tmpa_tl } } ; \fp_add:Nn \l__mermap_tmpa_fp { \l__mermap_result_fp } } \__mermap_compute_network_step:nn { \l__mermap_tex_width_fp } { \l__mermap_mapeast_fp - \l__mermap_mapwest_fp } \fp_set:Nn \l__mermap_tmpa_fp { ceil( \l__mermap_mapwest_fp / \l__mermap_result_fp )* \l__mermap_result_fp } \fp_compare:nNnT { \l__mermap_tmpa_fp - \l__mermap_mapwest_fp } < { 1e-10 } { \fp_add:Nn \l__mermap_tmpa_fp { \l__mermap_result_fp } } \fp_while_do:nNnn { \l__mermap_tmpa_fp } < { \l__mermap_mapeast_fp } { \tl_set:Nn \l__mermap_tmpa_tl { \fp_use:N \l__mermap_tmpa_fp } \draw[gray,very~thin] ( mrc~cs \c_colon_str lon = \l__mermap_tmpa_tl, lat = \mrcmapsouth ) coordinate ( mermap_temp ) node [ above=1mm,inner~sep=0.5pt,black!50!gray, font = \l__mermap_network_font_tl, fill=white,opacity=0.3,text~opacity=1, ] { \mrcformlon { \l__mermap_tmpa_tl } } -- (mermap_temp |- mrcmap.north) node [ below=1mm,inner~sep=0.5pt,black!50!gray, font = \l__mermap_network_font_tl, fill=white,opacity=0.3,text~opacity=1, ] { \mrcformlon { \l__mermap_tmpa_tl } } ; \fp_add:Nn \l__mermap_tmpa_fp { \l__mermap_result_fp } } \end{ scope } } %---- scaling and formatting --------------------------------------------------- \tl_new:N \l__mermap_temp_tl \keys_define:nn { mermap } { format~south .cs_set:Np = \__mermap_format_south:n #1, format~north .cs_set:Np = \__mermap_format_north:n #1, format~east .cs_set:Np = \__mermap_format_east:n #1, format~west .cs_set:Np = \__mermap_format_west:n #1, __format_angle .cs_set:Np = \__mermap_format_angle:n #1, format~angle .choice:, format~angle .value_required:n = true, format~angle / decimal .meta:nn = { mermap } { __format_angle = \ang{##1}}, format~angle / decimal-0 .meta:nn = { mermap } { __format_angle = { \ang[ round-mode=places,round-precision=0 ] {##1}}}, format~angle / decimal-1 .meta:nn = { mermap } { __format_angle = { \ang[ round-mode=places,round-precision=1 ] {##1}}}, format~angle / decimal-2 .meta:nn = { mermap } { __format_angle = { \ang[ round-mode=places,round-precision=2 ] {##1}}}, format~angle / decimal-3 .meta:nn = { mermap } { __format_angle = { \ang[ round-mode=places,round-precision=3 ] {##1}}}, format~angle / decimal-4 .meta:nn = { mermap } { __format_angle = { \ang[ round-mode=places,round-precision=4 ] {##1}}}, format~angle / degree .meta:nn = { mermap } { format~angle = decimal-0 }, format~angle / minute .meta:nn = { mermap } { __format_angle = \__mermap_format_angle_minute:n {##1}}, format~angle / second .meta:nn = { mermap } { __format_angle = \__mermap_format_angle_second:n {##1}}, format~NEWS~absolute .meta:nn = { mermap } { format~south = {##1}, format~north = {##1}, format~east = {##1}, format~west = {##1} }, format~NEWS~numeric .meta:nn = { mermap } { format~south = { $-$ ##1 }, format~north = {##1}, format~east = {##1}, format~west = { $-$ ##1 } }, } \keys_set:nn { mermap } { format~south = { #1\,S }, format~north = { #1\,N }, format~east = { #1\,E }, format~west = { #1\,W }, format~angle = decimal-4, } \NewExpandableDocumentCommand \mrckmtotex { m } { \fp_to_dim:n { (#1) / \l__mermap_scale_fp } } \NewExpandableDocumentCommand \mrcmiletotex { m } { \fp_to_dim:n { (#1) * \c__mermap_mile_fp / \l__mermap_scale_fp } } \NewExpandableDocumentCommand \mrctextokm { m } { \fp_to_decimal:n { (#1) * \l__mermap_scale_fp } } \NewExpandableDocumentCommand \mrctextomile { m } { \fp_to_decimal:n { (#1) / \c__mermap_mile_fp * \l__mermap_scale_fp } } \NewDocumentCommand \mrcprettymapscale { } { 1 \, \c_colon_str \, \num[round-mode=figures,round-precision=3,detect-all] { \fp_to_decimal:N \l__mermap_scale_denominator_fp } } \cs_new_protected_nopar:Npn \__mermap_pretty_distance:n #1 { \fp_set:Nn \l__mermap_tmpa_fp { #1 } \fp_compare:nNnTF { \l__mermap_tmpa_fp } < { 5 } { \SI[round-mode=figures,round-precision=3,detect-all] { \fp_to_decimal:n { 1000* \l__mermap_tmpa_fp } } { \meter } } { \SI[round-mode=figures,round-precision=3,detect-all] { \fp_to_decimal:N \l__mermap_tmpa_fp } { \kilo \meter } } } \cs_new_protected_nopar:Npn \__mermap_pretty_length:n #1 { \fp_set:Nn \l__mermap_tmpa_fp { (#1)* \l__mermap_scale_fp } \fp_compare:nNnTF { \l__mermap_tmpa_fp } < { 5 } { \SI[round-mode=figures,round-precision=3,detect-all] { \fp_to_decimal:n { 1000* \l__mermap_tmpa_fp } } { \meter } } { \SI[round-mode=figures,round-precision=3,detect-all] { \fp_to_decimal:N \l__mermap_tmpa_fp } { \kilo \meter } } } \NewDocumentCommand \mrcprettymapwidth { } { \__mermap_pretty_length:n { \mrctexwidth } } \NewDocumentCommand \mrcprettymapheight { } { \__mermap_pretty_length:n { \mrctexheight } } \NewDocumentCommand \mrcprettymapresolution { } { \SI[round-mode=places,round-precision=0,detect-all] { \fp_to_decimal:n { 1in* \l__mermap_pixel_width_tl / \l__mermap_tex_width_fp } } { dpi } } \NewDocumentCommand \mrcprettytilesize { } { \SI[round-mode=places,round-precision=3,detect-all] { \fp_to_decimal:n { \l__mermap_tile_size_dim /1mm } } { \milli \meter } } \cs_new_protected_nopar:Npn \__mermap_format_angle_minute:n #1 { \fp_set:Nn \l__mermap_tmpa_fp { floor(#1) } \fp_set:Nn \l__mermap_tmpb_fp { round((#1 - \l__mermap_tmpa_fp )*60) } \ang[add-arc-degree-zero,add-arc-minute-zero] { \fp_to_int:N \l__mermap_tmpa_fp ; \fp_to_int:N \l__mermap_tmpb_fp ; } } \cs_new_protected_nopar:Npn \__mermap_format_angle_second:n #1 { \fp_set:Nn \l__mermap_tmpa_fp { floor(#1) } \fp_set:Nn \l__mermap_tmpb_fp { floor((#1 - \l__mermap_tmpa_fp )*60) } \ang[add-arc-degree-zero,add-arc-minute-zero] { \fp_to_int:N \l__mermap_tmpa_fp ; \fp_to_int:N \l__mermap_tmpb_fp ; \fp_to_int:n { round(((#1 - \l__mermap_tmpa_fp )*60 - \l__mermap_tmpb_fp )*60) } } } \NewDocumentCommand \mrcformlat { o m } { \group_begin: \IfNoValueF {#1} { \keys_set:nn { mermap } {#1} } \fp_set:Nn \l__mermap_tmpa_fp {#2} \fp_compare:nNnTF { \l__mermap_tmpa_fp } < { 0 } { \tl_set:Ne \l__mermap_temp_tl { \fp_to_decimal:n { - \l__mermap_tmpa_fp } } \__mermap_format_south:n { \__mermap_format_angle:n { \l__mermap_temp_tl } } } { \tl_set:Ne \l__mermap_temp_tl { \fp_to_decimal:N \l__mermap_tmpa_fp } \__mermap_format_north:n { \__mermap_format_angle:n { \l__mermap_temp_tl } } } \group_end: } \NewDocumentCommand \mrcformlon { o m } { \group_begin: \IfNoValueF {#1} { \keys_set:nn { mermap } {#1} } \fp_set:Nn \l__mermap_tmpa_fp { #2-360*floor((#2+180)/360) } \fp_compare:nNnTF { \l__mermap_tmpa_fp } < { 0 } { \tl_set:Ne \l__mermap_temp_tl { \fp_to_decimal:n { - \l__mermap_tmpa_fp } } \__mermap_format_west:n { \__mermap_format_angle:n { \l__mermap_temp_tl } } } { \tl_set:Ne \l__mermap_temp_tl { \fp_to_decimal:N \l__mermap_tmpa_fp } \__mermap_format_east:n { \__mermap_format_angle:n { \l__mermap_temp_tl } } } \group_end: } %---- scale bars --------------------------------------------------------------- \bool_new:N \l__mermap_scalebar_double_bool \bool_new:N \l__mermap_scalebar_transparent_bool \dim_new:N \l__mermap_scalebar_height_dim \fp_new:N \l__mermap_scalebar_width_fp \int_new:N \l__mermap_scalebar_partitions_int \cs_new_protected_nopar:Npn \__mermap_scalebar_positioning:w #1#2#3#4#5;#6;#7 \q_stop { \tl_if_empty:nTF {#5} { \fp_set:Nn \l__mermap_tmpa_fp { 0 } \fp_set:Nn \l__mermap_tmpb_fp { 0 } } { \fp_set:Nn \l__mermap_tmpa_fp { #3*(#5) } \tl_if_empty:nTF {#6} { \fp_set:Nn \l__mermap_tmpb_fp { #4*(#5) } } { \fp_set:Nn \l__mermap_tmpb_fp { #4*(#6) } } } \tl_set:Ne \l__mermap_scalebar_at_tl { { ( [ xshift = \fp_to_dim:N \l__mermap_tmpa_fp, yshift = \fp_to_dim:N \l__mermap_tmpb_fp ] mrcmap.#1 ) } } \tl_set:Nn \l__mermap_scalebar_placement_tl {#2} } \keys_define:nn { mermap/scalebar } { width-in-km .fp_set:N = \l__mermap_scalebar_width_fp, width-in-kilometer .meta:nn = { mermap/scalebar } { width-in-km = {#1} }, width-in-meter .meta:nn = { mermap/scalebar } { width-in-km = { (#1)/1000 } }, width-in-mile .meta:nn = { mermap/scalebar } { width-in-km = { (#1)* \c__mermap_mile_fp } }, width-in-yard .meta:nn = { mermap/scalebar } { width-in-km = { (#1)*0.0009144 } }, partitions .int_set:N = \l__mermap_scalebar_partitions_int, height .dim_set:N = \l__mermap_scalebar_height_dim, at .tl_set:N = \l__mermap_scalebar_at_tl, placement .tl_set:N = \l__mermap_scalebar_placement_tl, major~style .code:n = \tikzset{ mrcscalebarmajor/.style = {#1} }, minor~style .code:n = \tikzset{ mrcscalebarminor/.style = {#1} }, double .bool_set:N = \l__mermap_scalebar_double_bool, single .bool_set_inverse:N = \l__mermap_scalebar_double_bool, transparent .bool_set:N = \l__mermap_scalebar_transparent_bool, solid .bool_set_inverse:N = \l__mermap_scalebar_transparent_bool, scale .code:n = { \fp_set:Nn \l__mermap_scale_fp { #1 / (1cm*100000) }}, south-east-inside .code:n = { \__mermap_scalebar_positioning:w { south~east } { above~left } { -1 } { 1 } #1 ;; \q_stop }, south-east-outside .code:n = { \__mermap_scalebar_positioning:w { south~east } { below~left } { -1 } { -1 } #1 ;; \q_stop }, south-west-inside .code:n = { \__mermap_scalebar_positioning:w { south~west } { above~right } { 1 } { 1 } #1 ;; \q_stop }, south-west-outside .code:n = { \__mermap_scalebar_positioning:w { south~west } { below~right } { 1 } { -1 } #1 ;; \q_stop }, north-west-inside .code:n = { \__mermap_scalebar_positioning:w { north~west } { below~right } { 1 } { -1 } #1 ;; \q_stop }, north-west-outside .code:n = { \__mermap_scalebar_positioning:w { north~west } { above~right } { 1 } { 1 } #1 ;; \q_stop }, north-east-inside .code:n = { \__mermap_scalebar_positioning:w { north~east } { below~left } { -1 } { -1 } #1 ;; \q_stop }, north-east-outside .code:n = { \__mermap_scalebar_positioning:w { north~east } { above~left } { -1 } { 1 } #1 ;; \q_stop }, } \keys_set:nn { mermap/scalebar } { width-in-km = 0, partitions = 5, double = true, transparent = true, height = 2mm, at = { (0,0) }, placement =, major~style =, minor~style =, } \cs_new_protected_nopar:Npn \__mermap_drawscalebar: { \exp_last_unbraced:Ne \node { [ rectangle, name = mrcscalebar, at = { \exp_not:V \l__mermap_scalebar_at_tl }, \exp_not:V \l__mermap_scalebar_placement_tl, line~width = 0mm, inner~sep = 0mm, outer~sep = 0mm, draw = none, fill = none, minimum~width = \mrckmtotex { \l__mermap_scalebar_width_fp }, minimum~height = \l__mermap_scalebar_height_dim ] } {} ; \begin{ scope } [ shift = (mrcscalebar.south~west) ] \__mermap_tikz_path_begin:n { fill=black, mrcscalebarmajor } \pgfseteorule \fp_set:Nn \l__mermap_tmpa_fp { \l__mermap_scalebar_width_fp / \l__mermap_scale_fp } \pgfpathrectangle { \pgfpoint { 0pt } { 0pt }} { \pgfpoint { \fp_to_dim:N \l__mermap_tmpa_fp } { \l__mermap_scalebar_height_dim }} \bool_if:NF \l__mermap_scalebar_transparent_bool { \__mermap_tikz_path_end: \__mermap_tikz_path_begin:n { fill=white, mrcscalebarminor } \fp_set:Nn \l__mermap_tmpa_fp { \l__mermap_scalebar_width_fp / \l__mermap_scale_fp } } \fp_set:Nn \l__mermap_tmpb_fp { \l__mermap_tmpa_fp / \l__mermap_scalebar_partitions_int } \bool_if:NTF \l__mermap_scalebar_double_bool { \dim_set:Nn \l__mermap_tmpb_dim { \l__mermap_scalebar_height_dim / 2 } \dim_set:Nn \l__mermap_tmpa_dim { 0.2pt - \l__mermap_tmpb_dim } \int_compare:nNnTF { \l__mermap_scalebar_partitions_int } = { 1 } { \pgfpathrectangle { \pgfpoint{ 0.2pt } { \l__mermap_tmpb_dim }} { \pgfpoint{ \fp_to_dim:n { \l__mermap_tmpb_fp -0.4pt }} { \l__mermap_tmpa_dim }} } { \pgfpathrectangle { \pgfpoint{ 0.2pt } { \l__mermap_tmpb_dim }} { \pgfpoint{ \fp_to_dim:n { \l__mermap_tmpb_fp -0.2pt }} { \l__mermap_tmpa_dim }} } \int_step_inline:nn { \l__mermap_scalebar_partitions_int - 1 } { \dim_set:Nn \l__mermap_tmpa_dim { - \l__mermap_tmpa_dim } \int_compare:nNnTF { ##1 +1 } = { \l__mermap_scalebar_partitions_int } { \pgfpathrectangle { \pgfpoint { \fp_to_dim:n { ##1* \l__mermap_tmpb_fp }} { \l__mermap_tmpb_dim }} { \pgfpoint { \fp_to_dim:n { \l__mermap_tmpb_fp -0.2pt }} { \l__mermap_tmpa_dim }} } { \pgfpathrectangle { \pgfpoint { \fp_to_dim:n { ##1* \l__mermap_tmpb_fp }} { \l__mermap_tmpb_dim }} { \pgfpoint { \fp_to_dim:N \l__mermap_tmpb_fp } { \l__mermap_tmpa_dim }} } } } { \dim_set:Nn \l__mermap_tmpa_dim { \l__mermap_scalebar_height_dim - 0.4pt } \int_step_inline:nnnn { 1 } { 2 } { \l__mermap_scalebar_partitions_int - 1 } { \int_compare:nNnTF { ##1 +1 } = { \l__mermap_scalebar_partitions_int } { \pgfpathrectangle { \pgfpoint{ \fp_to_dim:n { ##1* \l__mermap_tmpb_fp }} { 0.2pt }} { \pgfpoint{ \fp_to_dim:n { \l__mermap_tmpb_fp -0.2pt }} { \l__mermap_tmpa_dim }} } { \pgfpathrectangle { \pgfpoint{ \fp_to_dim:n { ##1* \l__mermap_tmpb_fp }} { 0.2pt }} { \pgfpoint{ \fp_to_dim:N \l__mermap_tmpb_fp } { \l__mermap_tmpa_dim }} } } } \__mermap_tikz_path_end: \end{ scope } } \msg_new:nnnn { mercatormap } { scalebar-too-large } { The~width~of~the~scale~bar~is~too~large:~#1. } { You~should~provide~a~smaller~value~by~using~width-in-km~or~width-in-mile. } \msg_new:nnnn { mercatormap } { scalebar-scale-unset } { The~map~scale~is~unknown. } { Use~\token_to_str:N \mrcdrawscalebar \ with~a~defined~map~or~set~'scale'~ explicitely. } \NewDocumentCommand \mrcdrawscalebar { o } { \group_begin: \IfNoValueF {#1} { \keys_set:nn { mermap/scalebar } {#1} } \fp_compare:nNnT { \l__mermap_scale_fp } = { 0 } { \msg_error:nn { mercatormap } { scalebar-scale-unset } } \fp_compare:nNnT { \l__mermap_scalebar_width_fp / \l__mermap_scale_fp } > { 575cm } { \msg_error:nne { mercatormap } { scalebar-too-large } { \fp_to_dim:n { \l__mermap_scalebar_width_fp / \l__mermap_scale_fp } } } \__mermap_drawscalebar: \group_end: } %---- markers ------------------------------------------------------------------ \bool_new:N \l__mermap_marker_show_bool \bool_new:N \l__mermap_marker_use_links_bool \bool_new:N \l__mermap_marker_use_urls_bool \fp_new:N \l__mermap_marker_angle_fp \fp_new:N \l__mermap_marker_distance_fp \fp_new:N \l__mermap_marker_inner_radius_fp \fp_new:N \l__mermap_marker_latitude_fp \fp_new:N \l__mermap_marker_longitude_fp \fp_new:N \l__mermap_marker_radius_fp \fp_new:N \l__mermap_marker_shift_fp \tl_new:N \l__mermap_every_marker_first_tl \tl_new:N \l__mermap_every_marker_last_tl \tl_new:N \l__mermap_marker_alias_tl \tl_new:N \l__mermap_marker_category_tl \tl_new:N \l__mermap_marker_contents_tl \tl_new:N \l__mermap_marker_font_tl \tl_new:N \l_mermap_marker_generic_tl \tl_new:N \l__mermap_marker_link_tl \tl_new:N \l__mermap_marker_pictocontents_tl \tl_new:N \l__mermap_marker_type_tl \tl_new:N \l__mermap_marker_url_tl \tl_new:N \l_mermap_marker_uuid_tl \exp_last_unbraced:NNV \cs_new_nopar:Npn \__mermap_marker_position:w \c__mermap_argone_colon_argtwo_tl \q_stop { \fp_set:Nn \l__mermap_marker_latitude_fp {#1} \fp_set:Nn \l__mermap_marker_longitude_fp {#2} } \keys_define:nn { mermap/marker } { latitude .fp_set:N = \l__mermap_marker_latitude_fp, lat .fp_set:N = \l__mermap_marker_latitude_fp, longitude .fp_set:N = \l__mermap_marker_longitude_fp, lon .fp_set:N = \l__mermap_marker_longitude_fp, position .code:n = { \__mermap_marker_position:w #1 \q_stop }, named~position .meta:nn = { mermap/marker } { latitude=\mrcNPlat{#1}, longitude=\mrcNPlon{#1} }, use~inside .choice: =, use~inside .value_required:n = true, use~inside/map .code:n = { \cs_set_eq:NN \__mermap_if_marker_inside:nnTF \__mermap_if_in_map:nnTF }, use~inside/vicinity .code:n = { \cs_set_eq:NN \__mermap_if_marker_inside:nnTF \__mermap_if_in_vicinity:nnTF }, alias .tl_set:N = \l__mermap_marker_alias_tl, contents .tl_set:N = \l__mermap_marker_contents_tl, pictocontents .tl_set:N = \l__mermap_marker_pictocontents_tl, uuid .tl_set:N = \l_mermap_marker_uuid_tl, generic .tl_set:N = \l_mermap_marker_generic_tl, url .tl_set:N = \l__mermap_marker_url_tl, link .tl_set:N = \l__mermap_marker_link_tl, category .tl_set:N = \l__mermap_marker_category_tl, type .tl_set:N = \l__mermap_marker_type_tl, angle .fp_set:N = \l__mermap_marker_angle_fp, shift .fp_set:N = \l__mermap_marker_shift_fp, distance .fp_set:N = \l__mermap_marker_distance_fp, draw .code:n = \colorlet{ mrcmarkerdraw } {#1}, fill .code:n = \colorlet{ mrcmarkerfill } {#1}, text .code:n = \colorlet{ mrcmarkertext } {#1}, font .tl_set:N = \l__mermap_marker_font_tl, radius .fp_set:N = \l__mermap_marker_radius_fp, inner~radius .fp_set:N = \l__mermap_marker_inner_radius_fp, path~style .code:n = {\tikzset{ mrcpathstyle/.style = {#1} }}, node~style .code:n = {\tikzset{ mrcnodestyle/.style = {#1} }}, show .bool_set:N = \l__mermap_marker_show_bool, hide .bool_set_inverse:N = \l__mermap_marker_show_bool, show~category .code:n = { \str_if_eq:VnT \l__mermap_marker_category_tl {#1} { \bool_set_true:N \l__mermap_marker_show_bool } }, show~all~but~category .code:n = { \str_if_eq:VnF \l__mermap_marker_category_tl {#1} { \bool_set_true:N \l__mermap_marker_show_bool } }, hide~category .code:n = { \str_if_eq:VnT \l__mermap_marker_category_tl {#1} { \bool_set_false:N \l__mermap_marker_show_bool } }, hide~all~but~category .code:n = { \str_if_eq:VnF \l__mermap_marker_category_tl {#1} { \bool_set_false:N \l__mermap_marker_show_bool } }, use~links .bool_set:N = \l__mermap_marker_use_links_bool, ignore~links .bool_set_inverse:N = \l__mermap_marker_use_links_bool, use~urls .bool_set:N = \l__mermap_marker_use_urls_bool, ignore~urls .bool_set_inverse:N = \l__mermap_marker_use_urls_bool, first~options .tl_set:N = \l__mermap_every_marker_first_tl, last~options .tl_set:N = \l__mermap_every_marker_last_tl, style .choice: =, style .value_required:n = true, } \keys_set:nn { mermap/marker } { latitude = 12, longitude = 49, use~inside = map, contents =, alias = noname, pictocontents =, angle = 90, shift = 0pt, distance = 5mm, fill = gray!20, draw = gray, text = black, radius = 3mm, inner~radius = 2.25mm, path~style =, node~style =, font = \sffamily\small, type = classic, uuid =, generic =, url =, link =, category =, show = true, use~links = true, use~urls = true, } \NewDocumentCommand \mrcmarkercontents {} { \tl_use:N \l__mermap_marker_contents_tl } \NewDocumentCommand \mrcmarkerpictocontents {} { \tl_use:N \l__mermap_marker_pictocontents_tl } \NewDocumentCommand \mrcmarkergeneric {} { \tl_use:N \l_mermap_marker_generic_tl } \NewDocumentCommand \mrcmarkerfont {} { \tl_use:N \l__mermap_marker_font_tl } \NewExpandableDocumentCommand \mrcmarkerlatitude {} { \fp_to_decimal:N \l__mermap_marker_latitude_fp } \NewExpandableDocumentCommand \mrcmarkerlongitude {} { \fp_to_decimal:N \l__mermap_marker_longitude_fp } \NewExpandableDocumentCommand \mrcmarkeruuid {} { \tl_use:N \l_mermap_marker_uuid_tl } \NewExpandableDocumentCommand \mrcmarkercategory {} { \tl_use:N \l__mermap_marker_category_tl } \NewExpandableDocumentCommand \mrcmarkerangle {} { \fp_to_decimal:N \l__mermap_marker_angle_fp } \NewExpandableDocumentCommand \mrcmarkershift {} { \fp_to_dim:N \l__mermap_marker_shift_fp } \NewExpandableDocumentCommand \mrcmarkerdistance {} { \fp_to_dim:N \l__mermap_marker_distance_fp } \NewExpandableDocumentCommand \mrcmarkerradius {} { \fp_to_dim:N \l__mermap_marker_radius_fp } \NewExpandableDocumentCommand \mrcmarkerinnerradius {} { \fp_to_dim:N \l__mermap_marker_inner_radius_fp } \NewDocumentCommand \mrcnewmarkerstyle { m +m } { \keys_define:nn { mermap/marker/style } { #1 .meta:nn = { mermap/marker } {#2} } } \msg_new:nnnn { mercatormap } { markertype-undefined } { Marker~type~'#1'~is~unknown. } { I~guess~'type=#1'~for~setting~a~marker~type~contains~a~spelling~error. } \cs_new_nopar:Npn \__mermap_hyper_path:n #1 { \pgfpointanchor { path~picture~bounding~box } { south~west } \pgf@xb-\pgf@x \pgf@yb-\pgf@y \pgfpointanchor { path~picture~bounding~box } { north~east } \advance\pgf@xb\pgf@x \advance\pgf@yb\pgf@y \advance\pgf@x-1bp \advance\pgf@y-1bp \advance\pgf@xb-2bp \advance\pgf@yb-2bp \pgftext [ at = {\pgfqpoint{\pgf@x} {\pgf@y}}, right, top ] { \hypersetup { pdfborder = 0~0~0 } #1{\vrule height\pgf@yb depth0ptwidth0pt\vrule height0ptdepth0ptwidth\pgf@xb} } } \cs_new_nopar:Npn \__mermap_hyper_path_insert: { \cs_if_exist:NT \hypersetup { \bool_if:NT \l__mermap_marker_use_urls_bool { \tl_if_empty:NF \l__mermap_marker_url_tl { \__mermap_hyper_path:n { \href { \l__mermap_marker_url_tl } } } } \bool_if:NT \l__mermap_marker_use_links_bool { \tl_if_empty:NF \l__mermap_marker_link_tl { \__mermap_hyper_path:n { \hyperlink { \l__mermap_marker_link_tl } } } } } } \tikzset { mrchyperpath/.style = { path~picture = { \__mermap_hyper_path_insert: } } } \NewDocumentCommand \mrcmarker { m } { \group_begin: \keys_set:nV { mermap/marker } \l__mermap_every_marker_first_tl \keys_set:nn { mermap/marker } { #1 } \keys_set:nV { mermap/marker } \l__mermap_every_marker_last_tl \__mermap_if_marker_inside:nnTF { \l__mermap_marker_latitude_fp } { \l__mermap_marker_longitude_fp } { \bool_if:NT \l__mermap_marker_show_bool { \pgfnodealias { \l__mermap_marker_alias_tl } { mrcpos } \begin{ scope } [ shift=(mrcpos) ] \cs_if_exist_use:cF { __mermap_drawmarker_ \l__mermap_marker_type_tl } { \msg_error:nne { mercatormap } { markertype-undefined } { \l__mermap_marker_type_tl } } \end{ scope } } } {} \group_end: } \cs_new_protected:Npn \__mermap_new_marker_type:nn #1 { \cs_new:cpn { __mermap_drawmarker_#1 } } \NewDocumentCommand \mrcnewmarkertype { m } { \__mermap_new_marker_type:nn {#1} } \__mermap_new_marker_type:nn { classic } { \node [ circle,fill=black,inner~sep=0pt,minimum~width=4pt, pin = { [ text=mrcmarkertext, font=\mrcmarkerfont, pin~distance=\mrcmarkerradius, pin~position=\mrcmarkerangle, mrcnodestyle, mrchyperpath ] \mrcmarkercontents } ] {} ; } \__mermap_new_marker_type:nn { pin } { \tl_set:Ne \l__mermap_tmpa_tl { \fp_to_dim:N \l__mermap_marker_distance_fp } \path[fill=mrcmarkerfill,draw=none,fill~opacity=0.7] (0,0) -- (0.1, \l__mermap_tmpa_tl ) -- (-0.1, \l__mermap_tmpa_tl ) -- cycle; \node[fill=white,draw=none,text=mrcmarkertext, above,font=\mrcmarkerfont,inner~sep=0.5mm,align=center, line~width=0mm,xshift=\mrcmarkershift, fill~opacity=0.7,text~opacity=1,xshift=0mm,mrcnodestyle,mrchyperpath] (pin_node) at (0, \l__mermap_tmpa_tl ) {\mrcmarkercontents} ; \path[draw=mrcmarkerdraw,fill=none,line~join=round,mrcpathstyle] (0,0) -- (0.1, \l__mermap_tmpa_tl ) -- (pin_node.south~east) -- (pin_node.north~east) -- (pin_node.north~west) -- (pin_node.south~west) -- (-0.1, \l__mermap_tmpa_tl ) [line~join=bevel] -- cycle; } \__mermap_new_marker_type:nn { pinflip } { \tl_set:Ne \l__mermap_tmpa_tl { \fp_to_dim:N \l__mermap_marker_distance_fp } \path[fill=mrcmarkerfill,draw=none,fill~opacity=0.7] (0,0) -- (-0.1,- \l__mermap_tmpa_tl ) -- (0.1,- \l__mermap_tmpa_tl ) -- cycle; \node[fill=white,draw=none,text=mrcmarkertext, below,font=\mrcmarkerfont,inner~sep=0.5mm,align=center, line~width=0mm,xshift=\mrcmarkershift, fill~opacity=0.7,text~opacity=1,xshift=0mm,mrcnodestyle,mrchyperpath] (pin_node) at (0,- \l__mermap_tmpa_tl ) {\mrcmarkercontents} ; \path[draw=mrcmarkerdraw,fill=none,line~join=round,mrcpathstyle] (0,0) -- (-0.1,- \l__mermap_tmpa_tl ) -- (pin_node.north~west) -- (pin_node.south~west) -- (pin_node.south~east) -- (pin_node.north~east) -- (0.1,- \l__mermap_tmpa_tl ) [line~join=bevel] -- cycle; } \cs_new_protected_nopar:Npn \__mermap_tikz_drop_path:n #1 { \tl_set:Nn \l__mermap_tmpa_tl { \fp_to_dim:N \l__mermap_marker_radius_fp } \tl_set:Nn \l__mermap_tmpb_tl { \fp_to_dim:n { \l__mermap_marker_radius_fp *0.552 } } \__mermap_tikz_path_begin:n { line~join=bevel,draw=mrcmarkerdraw,fill=mrcmarkerfill,mrcpathstyle,mrchyperpath } \pgfpathmoveto { \pgfpoint { 0pt } { \fp_to_dim:n { -2* \l__mermap_marker_radius_fp - \l__mermap_marker_shift_fp } } } \pgfpathcurveto { \pgfpoint { \l__mermap_tmpb_tl } { - \l__mermap_tmpa_tl }} { \pgfpoint { \l__mermap_tmpa_tl } { - \l__mermap_tmpb_tl }} { \pgfpoint { \l__mermap_tmpa_tl } { 0pt }} \pgfpathcurveto { \pgfpoint { \l__mermap_tmpa_tl } { \l__mermap_tmpb_tl }} { \pgfpoint { \l__mermap_tmpb_tl } { \l__mermap_tmpa_tl }} { \pgfpoint { 0pt } { \l__mermap_tmpa_tl }} \pgfpathcurveto { \pgfpoint { - \l__mermap_tmpb_tl } { \l__mermap_tmpa_tl }} { \pgfpoint { - \l__mermap_tmpa_tl } { \l__mermap_tmpb_tl }} { \pgfpoint { - \l__mermap_tmpa_tl } { 0pt }} \pgfpathcurveto { \pgfpoint { - \l__mermap_tmpa_tl } { - \l__mermap_tmpb_tl }} { \pgfpoint { - \l__mermap_tmpb_tl } { - \l__mermap_tmpa_tl }} { \pgfpoint { 0pt } { \fp_to_dim:n { -2* \l__mermap_marker_radius_fp - \l__mermap_marker_shift_fp }}} \pgfpathclose #1 \__mermap_tikz_path_end: } \cs_new_protected_nopar:Npn \__mermap_tikz_circle_node: { \node[circle,inner~sep=0pt,font=\mrcmarkerfont,text=mrcmarkertext,mrcnodestyle] { \hbox_set:Nn \l__mermap_tmpa_box { \mrcmarkercontents } \fp_compare:nNnT { \box_wd:N \l__mermap_tmpa_box } > { 1.5* \l__mermap_marker_radius_fp } { \box_resize_to_wd_and_ht:Nnn \l__mermap_tmpa_box { \fp_to_dim:n { 1.5* \l__mermap_marker_radius_fp } } { \box_ht:N \l__mermap_tmpa_box } } \box_use_drop:N \l__mermap_tmpa_box } ; } \__mermap_new_marker_type:nn { drop } { \begin{ scope } [yshift = \fp_to_dim:n { 2* \l__mermap_marker_radius_fp + \l__mermap_marker_shift_fp } ] \__mermap_tikz_drop_path:n {} \__mermap_tikz_circle_node: \end{ scope } } \__mermap_new_marker_type:nn { pictodrop } { \begin{ scope } [yshift = \fp_to_dim:n { 2* \l__mermap_marker_radius_fp + \l__mermap_marker_shift_fp } ] \__mermap_tikz_drop_path:n {} \tl_use:N \l__mermap_marker_pictocontents_tl \end{ scope } } \__mermap_new_marker_type:nn { pictodropring } { \begin{ scope } [yshift = \fp_to_dim:n { 2* \l__mermap_marker_radius_fp + \l__mermap_marker_shift_fp } ] \group_begin: \pgfseteorule \__mermap_tikz_drop_path:n { \pgfpathcircle{ \pgfpoint { 0pt } { 0pt } } { \fp_to_dim:N \l__mermap_marker_inner_radius_fp } } \group_end: \tl_use:N \l__mermap_marker_pictocontents_tl \end{ scope } } \__mermap_new_marker_type:nn { knob } { \path[draw=mrcmarkerdraw,fill=mrcmarkerfill,mrcpathstyle,mrchyperpath] circle ( \fp_to_dim:N \l__mermap_marker_radius_fp ); \__mermap_tikz_circle_node: } \__mermap_new_marker_type:nn { pictoknob } { \path[draw=mrcmarkerdraw,fill=mrcmarkerfill,mrcpathstyle,mrchyperpath] circle ( \fp_to_dim:N \l__mermap_marker_radius_fp ); \tl_use:N \l__mermap_marker_pictocontents_tl } \__mermap_new_marker_type:nn { pictoknobring } { \path[draw=mrcmarkerdraw,fill=mrcmarkerfill,mrcpathstyle,mrchyperpath,even~odd~rule] circle ( \fp_to_dim:N \l__mermap_marker_radius_fp ) circle ( \fp_to_dim:N \l__mermap_marker_inner_radius_fp ); \tl_use:N \l__mermap_marker_pictocontents_tl } \__mermap_new_marker_type:nn { ringx } { \tl_set:Nn \l__mermap_tmpa_tl { \fp_to_dim:N \l__mermap_marker_radius_fp } \path[draw=mrcmarkerdraw,very~thin] (45 \c_colon_str \l__mermap_tmpa_tl )--(225 \c_colon_str \l__mermap_tmpa_tl ) (135 \c_colon_str \l__mermap_tmpa_tl )--(315 \c_colon_str \l__mermap_tmpa_tl ); \path[draw=mrcmarkerdraw,fill=mrcmarkerfill,mrcpathstyle,mrchyperpath,even~odd~rule] circle ( \l__mermap_tmpa_tl ) circle ( \fp_to_dim:N \l__mermap_marker_inner_radius_fp ); } \__mermap_new_marker_type:nn { markx } { \tl_set:Nn \l__mermap_tmpa_tl { \fp_to_dim:N \l__mermap_marker_radius_fp } \path[line~join=bevel,draw=mrcmarkerdraw,fill=mrcmarkerfill,mrcpathstyle,mrchyperpath] (0,0) -- (35 \c_colon_str \l__mermap_tmpa_tl ) -- (55 \c_colon_str \l__mermap_tmpa_tl ) -- cycle (0,0) -- (125 \c_colon_str \l__mermap_tmpa_tl ) -- (145 \c_colon_str \l__mermap_tmpa_tl ) -- cycle (0,0) -- (215 \c_colon_str \l__mermap_tmpa_tl ) -- (235 \c_colon_str \l__mermap_tmpa_tl ) -- cycle (0,0) -- (305 \c_colon_str \l__mermap_tmpa_tl ) -- (325 \c_colon_str \l__mermap_tmpa_tl ) -- cycle; } %---- paths and routes --------------------------------------------------------- \bool_new:N \l__mermap_path_first_point_bool \keys_define:nn { mermap } { every~route .code:n = { \tikzset{ mermap_every_route/.style = {#1} } } } \keys_set:nn { mermap } { every~route =, } \cs_new:Npn \__mermap_tikz_path_begin:n #1 { \path[#1] \pgfextra } \cs_new:Npn \__mermap_tikz_path_end: { \endpgfextra; } \cs_new_protected_nopar:Npn \__mermap_pgf_moveto_point:nn #1#2 { \pgfpathmoveto { \__mermap_pgfpoint:nn {#1} {#2} } } \cs_new_protected_nopar:Npn \__mermap_pgf_lineto_point:nn #1#2 { \pgfpathlineto { \__mermap_pgfpoint:nn {#1} {#2} } } \cs_new_protected_nopar:Npn \__mermap_route_point:nn #1#2 { \bool_if:NTF \l__mermap_path_first_point_bool { \__mermap_pgf_moveto_point:nn {#1} {#2} \bool_set_false:N \l__mermap_path_first_point_bool } { \__mermap_pgf_lineto_point:nn {#1} {#2} } } \cs_new_protected_nopar:Npn \__mermap_route_begin:n #1 { \__mermap_tikz_path_begin:n { draw,mermap_every_route,#1 } \cs_set_eq:NN \mrcpoint \__mermap_route_point:nn \bool_set_true:N \l__mermap_path_first_point_bool } \NewDocumentEnvironment { mrcroute } { O {} } { \__mermap_route_begin:n {#1} } { \__mermap_tikz_path_end: } \NewDocumentEnvironment { mrcroute* } { O {} } { \__mermap_route_begin:n {#1} } { \pgfpathclose \__mermap_tikz_path_end: } \NewDocumentCommand \mrcrouteinput { s O {} m } { \__mermap_route_begin:n {#2} \file_input:n {#3} \IfBooleanT {#1} { \pgfpathclose } \__mermap_tikz_path_end: } %---- orthodromes and loxodromes ----------------------------------------------- \fp_new:N \l__mermap_a_x_fp \fp_new:N \l__mermap_a_y_fp \fp_new:N \l__mermap_a_z_fp \fp_new:N \l__mermap_b_x_fp \fp_new:N \l__mermap_b_y_fp \fp_new:N \l__mermap_b_z_fp \fp_new:N \l__mermap_alpha_fp \fp_new:N \l__mermap_delta_lambda_fp \fp_new:N \l__mermap_delta_phi_fp \fp_new:N \l__mermap_n_x_fp \fp_new:N \l__mermap_n_y_fp \fp_new:N \l__mermap_n_z_fp \fp_new:N \l__mermap_psi_fp \fp_new:N \l__mermap_sin_psi_fp \fp_new:N \l__mermap_t_fp \fp_new:N \l__mermap_t_psi_fp \fp_new:N \l__mermap_t_x_fp \fp_new:N \l__mermap_t_y_fp \fp_new:N \l__mermap_t_z_fp \fp_const:Nn \c__mermap_linearization_threshold_fp { 10e-9 } \bool_new:N \l__mermap_linearization_bool \int_new:N \l__mermap_samples_int \keys_define:nn { mermap } { samples .int_set:N = \l__mermap_samples_int, } \keys_set:nn { mermap } { samples = 100, } \tikzset{ mermap~samples/.code = { \mermapset{ samples=#1 } } } \cs_new_protected_nopar:Npn \__mermap_sphere_point:nnn #1#2#3 % {x}{y}{z} { \fp_set:Nn \l__mermap_cs_lat_fp { asind(#3/sqrt((#1)^2+(#2)^2+(#3)^2)) } \fp_set:Nn \l__mermap_cs_lon_fp { sign(#2)*acosd(#1/sqrt((#1)^2+(#2)^2)) } \__mermap_pgfpoint:nn { \l__mermap_cs_lat_fp } { \l__mermap_cs_lon_fp } } \cs_new_protected_nopar:Npn \__mermap_unit_sphere_point:nnn #1#2#3 % {x}{y}{z} radius 1 { \fp_set:Nn \l__mermap_cs_lat_fp { asind(#3) } \fp_set:Nn \l__mermap_cs_lon_fp { sign(#2)*acosd(#1/sqrt((#1)^2+(#2)^2)) } \__mermap_pgfpoint:nn { \l__mermap_cs_lat_fp } { \l__mermap_cs_lon_fp } } \cs_new_protected:Npn \__mermap_draw_orthodrome:nnnnn #1#2#3#4#5 { \__mermap_tikz_path_begin:n { draw,mermap_every_route,#1 } \__mermap_setup_orthodrome:nnnn { #2 } { #3 } { #4 } { #5 } \__mermap_pgf_moveto_point:nn { #2 } { #3 } \int_step_inline:nn { \l__mermap_samples_int } { \__mermap_point_on_orthodrome:n { ##1 / \l__mermap_samples_int } \__mermap_pgf_lineto_point:nn { \l__mermap_cs_lat_fp } { \l__mermap_cs_lon_fp } } \__mermap_tikz_path_end: } \cs_new_protected:Npn \__mermap_setup_orthodrome:nnnn #1#2#3#4 { \fp_set:Nn \l__mermap_a_x_fp { cosd(#2)*cosd(#1) } \fp_set:Nn \l__mermap_a_y_fp { sind(#2)*cosd(#1) } \fp_set:Nn \l__mermap_a_z_fp { sind(#1) } \fp_set:Nn \l__mermap_b_x_fp { cosd(#4)*cosd(#3) } \fp_set:Nn \l__mermap_b_y_fp { sind(#4)*cosd(#3) } \fp_set:Nn \l__mermap_b_z_fp { sind(#3) } \fp_set:Nn \l__mermap_psi_fp { acosd( sind(#1)*sind(#3) + cosd(#1)*cosd(#3)*cosd(#4-(#2)) ) } \fp_set:Nn \l__mermap_sin_psi_fp { sind( \l__mermap_psi_fp ) } \bool_set:Nn \l__mermap_linearization_bool { \fp_compare_p:nNn { \l__mermap_psi_fp } < { \c__mermap_linearization_threshold_fp } } } \cs_new_protected:Npn \__mermap_point_on_orthodrome:n #1 { \fp_set:Nn \l__mermap_t_fp { #1 } \bool_if:NTF \l__mermap_linearization_bool { \fp_set:Nn \l__mermap_tmpa_fp { 1 - \l__mermap_t_fp } \fp_set_eq:NN \l__mermap_tmpb_fp \l__mermap_t_fp } { \fp_set:Nn \l__mermap_t_psi_fp { \l__mermap_t_fp * \l__mermap_psi_fp } \fp_set:Nn \l__mermap_tmpa_fp { sind( \l__mermap_psi_fp - \l__mermap_t_psi_fp ) / \l__mermap_sin_psi_fp } \fp_set:Nn \l__mermap_tmpb_fp { sind( \l__mermap_t_psi_fp ) / \l__mermap_sin_psi_fp } } \fp_set:Nn \l__mermap_t_x_fp { \l__mermap_tmpa_fp * \l__mermap_a_x_fp + \l__mermap_tmpb_fp * \l__mermap_b_x_fp } \fp_set:Nn \l__mermap_t_y_fp { \l__mermap_tmpa_fp * \l__mermap_a_y_fp + \l__mermap_tmpb_fp * \l__mermap_b_y_fp } \fp_set:Nn \l__mermap_t_z_fp { \l__mermap_tmpa_fp * \l__mermap_a_z_fp + \l__mermap_tmpb_fp * \l__mermap_b_z_fp } \fp_set:Nn \l__mermap_cs_lat_fp { asind( \l__mermap_t_z_fp ) } \fp_set:Nn \l__mermap_cs_lon_fp { sign( \l__mermap_t_y_fp ) * acosd( \l__mermap_t_x_fp /sqrt( \l__mermap_t_x_fp ^2 + \l__mermap_t_y_fp ^2)) } } \cs_new_protected:Npn \__mermap_angle_at_orthodrome: { \bool_if:NTF \l__mermap_linearization_bool { \fp_set:Nn \l__mermap_alpha_fp { 90 } } { \fp_set:Nn \l__mermap_tmpa_fp { cosd( \l__mermap_psi_fp - \l__mermap_t_psi_fp ) } \fp_set:Nn \l__mermap_tmpb_fp { cosd( \l__mermap_t_psi_fp ) } \fp_set:Nn \l__mermap_n_x_fp { \l__mermap_tmpb_fp * \l__mermap_b_x_fp - \l__mermap_tmpa_fp * \l__mermap_a_x_fp } \fp_set:Nn \l__mermap_n_y_fp { \l__mermap_tmpb_fp * \l__mermap_b_y_fp - \l__mermap_tmpa_fp * \l__mermap_a_y_fp } \fp_set:Nn \l__mermap_n_z_fp { \l__mermap_tmpb_fp * \l__mermap_b_z_fp - \l__mermap_tmpa_fp * \l__mermap_a_z_fp } \fp_set:Nn \l__mermap_tmpa_fp { sqrt( \l__mermap_n_x_fp ^2 + \l__mermap_n_y_fp ^2 + \l__mermap_n_z_fp ^2 ) } \fp_set:Nn \l__mermap_n_x_fp { \l__mermap_n_x_fp / \l__mermap_tmpa_fp } \fp_set:Nn \l__mermap_n_y_fp { \l__mermap_n_y_fp / \l__mermap_tmpa_fp } \fp_set:Nn \l__mermap_n_z_fp { \l__mermap_n_z_fp / \l__mermap_tmpa_fp } \fp_set:Nn \l__mermap_alpha_fp { acosd( \l__mermap_n_y_fp *cosd( \l__mermap_cs_lon_fp ) - \l__mermap_n_x_fp * sind( \l__mermap_cs_lon_fp ) ) } \fp_compare:nNnT { \l__mermap_n_z_fp } < { 0 } { \fp_set:Nn \l__mermap_alpha_fp { 360 - \l__mermap_alpha_fp } } } } \NewDocumentCommand \mrcdraworthodrome { O {} mmmm } { \__mermap_draw_orthodrome:nnnnn {#1} {#2} {#3} {#4} {#5} } \NewDocumentCommand \mrcNPdraworthodrome { O {} mm } { \__mermap_draw_orthodrome:nnnnn {#1} {\mrcNPlat{#2}} {\mrcNPlon{#2}} {\mrcNPlat{#3}} {\mrcNPlon{#3}} } \cs_new_protected_nopar:Npn \__mermap_ortho_distance:nnnn #1#2#3#4 { \fp_set:Nn \l__mermap_result_fp { \c__mermap_scale_radius_fp * acosd( sind(#1)*sind(#3) + cosd(#1)*cosd(#3)*cosd(#4-(#2)) ) } } \NewDocumentCommand \mrcstoreorthodistance { mmmmm } { \__mermap_ortho_distance:nnnn {#2} {#3} {#4} {#5} \cs_set_nopar:Npx #1 { \fp_to_decimal:N \l__mermap_result_fp } } \NewDocumentCommand \mrcprettyorthodistance { mmmm } { \__mermap_ortho_distance:nnnn {#1} {#2} {#3} {#4} \__mermap_pretty_distance:n { \l__mermap_result_fp } } \NewDocumentCommand \mrcNPprettyorthodistance { mm } { \__mermap_ortho_distance:nnnn {\mrcNPlat{#1}} {\mrcNPlon{#1}} {\mrcNPlat{#2}} {\mrcNPlon{#2}} \__mermap_pretty_distance:n { \l__mermap_result_fp } } \cs_new_protected_nopar:Npn \__mermap_loxo_distance:nnnn #1#2#3#4 { \fp_set:Nn \l__mermap_delta_phi_fp { (#3-(#1))/180*pi } \fp_set:Nn \l__mermap_delta_lambda_fp { (#4-(#2))/180*pi } \fp_compare:nNnTF { abs( \l__mermap_delta_phi_fp ) } < { 1e-5 } { \fp_set:Nn \l__mermap_tmpa_fp { tand(#1) } \fp_set:Nn \l__mermap_tmpb_fp { \l__mermap_delta_lambda_fp * cosd(#1) /( 1 + ( \l__mermap_tmpa_fp + (1+2* \l__mermap_tmpa_fp * \l__mermap_tmpa_fp ) * \l__mermap_delta_phi_fp /3)* \l__mermap_delta_phi_fp /2 ) } \fp_set:Nn \l__mermap_result_fp { sqrt( \l__mermap_delta_phi_fp * \l__mermap_delta_phi_fp + \l__mermap_tmpb_fp * \l__mermap_tmpb_fp ) } } { \fp_set:Nn \l__mermap_result_fp { abs( \l__mermap_delta_phi_fp ) * sqrt( 1+ ( \l__mermap_delta_lambda_fp /( ln(tand(#3/2+45)) - ln(tand(#1/2+45)) ) )^2 ) } } \fp_set:Nn \l__mermap_result_fp { \c__mermap_scale_radius_fp * 180/pi * \l__mermap_result_fp } } \NewDocumentCommand \mrcstoreloxodistance { mmmmm } { \__mermap_loxo_distance:nnnn {#2} {#3} {#4} {#5} \cs_set_nopar:Npx #1 { \fp_to_decimal:N \l__mermap_result_fp } } \NewDocumentCommand \mrcprettyloxodistance { mmmm } { \__mermap_loxo_distance:nnnn {#1} {#2} {#3} {#4} \__mermap_pretty_distance:n { \l__mermap_result_fp } } \NewDocumentCommand \mrcNPprettyloxodistance { mm } { \__mermap_loxo_distance:nnnn { \mrcNPlat{#1} } { \mrcNPlon{#1} } { \mrcNPlat{#2} } { \mrcNPlon{#2} } \__mermap_pretty_distance:n { \l__mermap_result_fp } } \cs_new_protected:Npn \__mermap_orthodrome_point:nnn #1#2#3 { \__mermap_point_on_orthodrome:n { #3 } \__mermap_set_named_position:nnn { #1 } { \l__mermap_cs_lat_fp } { \l__mermap_cs_lon_fp } \IfNoValueF { #2 } { \__mermap_angle_at_orthodrome: \cs_set:Npe #2 { \fp_to_decimal:N \l__mermap_alpha_fp } } } \NewDocumentCommand \mrcNPfromOrthoFraction { mo mm mm m } { \__mermap_setup_orthodrome:nnnn { #3 } { #4 } { #5 } { #6 } \__mermap_orthodrome_point:nnn { #1 } { #2 } { #7 } } \NewDocumentCommand \mrcNPfromOrthoFractionNamed { mo m m m } { \__mermap_setup_orthodrome:nnnn { \mrcNPlat{#3} } { \mrcNPlon{#3} } { \mrcNPlat{#4} } { \mrcNPlon{#4} } \__mermap_orthodrome_point:nnn { #1 } { #2 } { #5 } } \NewDocumentCommand \mrcNPfromOrthoDistance { mo mm mm m } { \__mermap_ortho_distance:nnnn { #3 } { #4 } { #5 } { #6 } \fp_compare:nNnTF { \l__mermap_result_fp } > { 0.001 } { \__mermap_setup_orthodrome:nnnn { #3 } { #4 } { #5 } { #6 } \__mermap_orthodrome_point:nnn { #1 } { #2 } { #7 / \l__mermap_result_fp } } { \__mermap_set_named_position:nnn { #1 } { #3 } { #4 } \IfNoValueF { #2 } { \cs_set:Npn #2 { 90 } } } } \NewDocumentCommand \mrcNPfromOrthoDistanceNamed { mo m m m } { \__mermap_ortho_distance:nnnn { \mrcNPlat{#3} } { \mrcNPlon{#3} } { \mrcNPlat{#4} } { \mrcNPlon{#4} } \fp_compare:nNnTF { \l__mermap_result_fp } > { 0.001 } { \__mermap_setup_orthodrome:nnnn { \mrcNPlat{#3} } { \mrcNPlon{#3} } { \mrcNPlat{#4} } { \mrcNPlon{#4} } \__mermap_orthodrome_point:nnn { #1 } { #2 } { #5 / \l__mermap_result_fp } } { \__mermap_set_named_position:nnn { #1 } { \mrcNPlat{#3} } { \mrcNPlon{#3} } \IfNoValueF { #2 } { \cs_set:Npn #2 { 90 } } } } %---- animations --------------------------------------------------------------- \bool_new:N \l__mermap_anim_drop_first_frame_bool \bool_new:N \l__mermap_anim_drop_last_frame_bool \fp_new:N \l__mermap_anim_a_lat_fp \fp_new:N \l__mermap_anim_a_lon_fp \fp_new:N \l__mermap_anim_a_scaledenom_fp \fp_new:N \l__mermap_anim_a_time_fp \fp_new:N \l__mermap_anim_b_lat_fp \fp_new:N \l__mermap_anim_b_lon_fp \fp_new:N \l__mermap_anim_b_scaledenom_fp \fp_new:N \l__mermap_anim_b_time_fp \fp_new:N \l_mermap_anim_angle_fp \fp_new:N \l_mermap_anim_lat_fp \fp_new:N \l_mermap_anim_lon_fp \fp_new:N \l_mermap_anim_scaledenom_fp \fp_new:N \l_mermap_anim_time_fp \int_new:N \l__mermap_anim_final_frame_int \int_new:N \l__mermap_anim_frames_int \int_new:N \l__mermap_anim_start_frame_int \int_new:N \l_mermap_anim_frame_int \seq_new:N \l__mermap_anim_scaledenom_seq \tl_new:N \l__mermap_anim_timescale_tl \tl_new:N \l__mermap_anim_timewarp_tl \NewExpandableDocumentCommand \mrcTimewarpIdentity { m } { #1 } \NewExpandableDocumentCommand \mrcTimewarpSlowStart { m m } { (#2)^(#1) } \NewExpandableDocumentCommand \mrcTimewarpSlowFinal { m m } { 1 - (1-#2)^(#1) } \NewExpandableDocumentCommand \mrcTimewarpSlowStartFinal { m m } { %1 - (1-#2)^(#1) #2 <= 0.5 ? (2*(#2))^(#1) / 2 : 1 - (2-2*(#2))^(#1) / 2 } \NewDocumentEnvironment { mrcAnimation } { m +b } { \keys_set:nn { mermap/anim } { #1 } \__mermap_anim_autocorrect_scaledenom_seq: \int_compare:nNnT { \l__mermap_anim_frames_int } < { 2 } { \int_set:Nn \l__mermap_anim_frames_int { 2 } } \bool_if:NTF \l__mermap_anim_drop_first_frame_bool { \int_set:Nn \l__mermap_anim_start_frame_int { 2 } } { \int_set:Nn \l__mermap_anim_start_frame_int { 1 } } \bool_if:NTF \l__mermap_anim_drop_last_frame_bool { \int_set:Nn \l__mermap_anim_final_frame_int { \l__mermap_anim_frames_int - 1 } } { \int_set:Nn \l__mermap_anim_final_frame_int { \l__mermap_anim_frames_int } } \__mermap_setup_orthodrome:nnnn { \l__mermap_anim_a_lat_fp } { \l__mermap_anim_a_lon_fp } { \l__mermap_anim_b_lat_fp } { \l__mermap_anim_b_lon_fp } \__mermap_anim_pop_time_scale:NN \l__mermap_anim_a_time_fp \l__mermap_anim_a_scaledenom_fp \__mermap_anim_pop_time_scale:NN \l__mermap_anim_b_time_fp \l__mermap_anim_b_scaledenom_fp \int_step_variable:nnNn { \l__mermap_anim_start_frame_int } { \l__mermap_anim_final_frame_int } \l_mermap_anim_frame_int { \fp_set:Nn \l_mermap_anim_time_fp { ( \l_mermap_anim_frame_int - 1 ) / ( \l__mermap_anim_frames_int - 1 ) } \fp_set:Nn \l_mermap_anim_time_fp { \l__mermap_anim_timewarp_tl { \l_mermap_anim_time_fp } } \__mermap_point_on_orthodrome:n { \l_mermap_anim_time_fp } \fp_set_eq:NN \l_mermap_anim_lat_fp \l__mermap_cs_lat_fp \fp_set_eq:NN \l_mermap_anim_lon_fp \l__mermap_cs_lon_fp \__mermap_set_named_position:nnn { AnimNP } { \l_mermap_anim_lat_fp } { \l_mermap_anim_lon_fp } \__mermap_angle_at_orthodrome: \fp_set_eq:NN \l_mermap_anim_angle_fp \l__mermap_alpha_fp \fp_while_do:nNnn \l_mermap_anim_time_fp > \l__mermap_anim_b_time_fp { \fp_set_eq:NN \l__mermap_anim_a_time_fp \l__mermap_anim_b_time_fp \fp_set_eq:NN \l__mermap_anim_a_scaledenom_fp \l__mermap_anim_b_scaledenom_fp \__mermap_anim_pop_time_scale:NN \l__mermap_anim_b_time_fp \l__mermap_anim_b_scaledenom_fp } \fp_set:Nn \l_mermap_anim_scaledenom_fp { round ( exp ( ln( \l__mermap_anim_a_scaledenom_fp ) + ( ln( \l__mermap_anim_b_scaledenom_fp ) - ln( \l__mermap_anim_a_scaledenom_fp ) ) * ( \l_mermap_anim_time_fp - \l__mermap_anim_a_time_fp ) / ( \l__mermap_anim_b_time_fp - \l__mermap_anim_a_time_fp ) ) ) } #2 } } {} \cs_new_protected:Npn \__mermap_anim_autocorrect_scaledenom_seq: { \seq_get_left:NN \l__mermap_anim_scaledenom_seq \l__mermap_anim_timescale_tl \bool_lazy_any:nTF { { \seq_if_empty_p:N \l__mermap_anim_scaledenom_seq } { \tl_if_empty_p:N \l__mermap_anim_timescale_tl } { \quark_if_no_value_p:N \l__mermap_anim_timescale_tl } } { \seq_set_split:Nnn \l__mermap_anim_scaledenom_seq { - } { 0/25000 - 1/25000 }, } { \fp_compare:nNnF { \__mermap_anim_use_time:o \l__mermap_anim_timescale_tl } = { 0 } { \seq_put_left:Ne \l__mermap_anim_scaledenom_seq { 0 / \__mermap_anim_use_scale:o \l__mermap_anim_timescale_tl } } } \seq_get_right:NNF \l__mermap_anim_scaledenom_seq \l__mermap_anim_timescale_tl { \msg_error:nn { mercatormap } { anim-scaledenom-invalid } } \fp_compare:nNnF { \__mermap_anim_use_time:o \l__mermap_anim_timescale_tl } = { 1 } { \seq_put_right:Ne \l__mermap_anim_scaledenom_seq { 1 / \__mermap_anim_use_scale:o \l__mermap_anim_timescale_tl } } \fp_set:Nn \l__mermap_anim_a_time_fp { -1 } \seq_map_inline:Nn \l__mermap_anim_scaledenom_seq { \fp_set:Nn \l__mermap_anim_b_time_fp { \__mermap_anim_use_time:n { ##1 } } \fp_compare:nNnTF \l__mermap_anim_a_time_fp < \l__mermap_anim_b_time_fp { \fp_set_eq:NN \l__mermap_anim_a_time_fp \l__mermap_anim_b_time_fp } { \msg_error:nn { mercatormap } { anim-scaledenom-invalid } } } } \cs_new_protected:Npn \__mermap_anim_pop_time_scale:NN #1#2 { \seq_pop_left:NN \l__mermap_anim_scaledenom_seq \l__mermap_anim_timescale_tl \fp_set:Nn #1 { \__mermap_anim_use_time:o \l__mermap_anim_timescale_tl } \fp_set:Nn #2 { \__mermap_anim_use_scale:o \l__mermap_anim_timescale_tl } } \msg_new:nnnn { mercatormap } { anim-scaledenom-invalid } { The~animation~scale~denominator~sequence~is~invalid. } { Check~\seq_use:Nn \l__mermap_anim_scaledenom_seq { ~-~ }~with~the~documentation.~ Time~values~are~not~strictly~monotonically~increasing. } \cs_new_protected_nopar:Npn \__mermap_anim_set_position:w #1 #2 / #3 \q_stop { \fp_set:cn { l__mermap_anim_#1_lat_fp } { #2 } \fp_set:cn { l__mermap_anim_#1_lon_fp } { #3 } } \cs_new_nopar:Npn \__mermap_anim_use_time:w #1 / #2 \q_stop { #1 } \cs_new_nopar:Npn \__mermap_anim_use_time:n #1 { \__mermap_anim_use_time:w #1 \q_stop } \cs_generate_variant:Nn \__mermap_anim_use_time:n { o } \cs_new_nopar:Npn \__mermap_anim_use_scale:w #1 / #2 \q_stop { #2 } \cs_new_nopar:Npn \__mermap_anim_use_scale:n #1 { \__mermap_anim_use_scale:w #1 \q_stop } \cs_generate_variant:Nn \__mermap_anim_use_scale:n { o } \keys_define:nn { mermap/anim } { start-position .code:n = \__mermap_anim_set_position:w { a } #1 \q_stop, final-position .code:n = \__mermap_anim_set_position:w { b } #1 \q_stop, position .meta:n = { start-position = #1, final-position = #1 }, named-start-position .code:n = { \fp_set:Nn \l__mermap_anim_a_lat_fp { \mrcNPlat{ #1 } } \fp_set:Nn \l__mermap_anim_a_lon_fp { \mrcNPlon{ #1 } } }, named-final-position .code:n = { \fp_set:Nn \l__mermap_anim_b_lat_fp { \mrcNPlat{ #1 } } \fp_set:Nn \l__mermap_anim_b_lon_fp { \mrcNPlon{ #1 } } }, named-position .meta:n = { named-start-position = #1, named-final-position = #1 }, frames .int_set:N = \l__mermap_anim_frames_int, drop-first-frame .bool_set:N = \l__mermap_anim_drop_first_frame_bool, drop-last-frame .bool_set:N = \l__mermap_anim_drop_last_frame_bool, drop-no-frame .meta:n = { drop-first-frame=false, drop-last-frame=false }, scale-denominators .code:n = \seq_set_split:Nnn \l__mermap_anim_scaledenom_seq { - } { #1 }, common-scale-denominator .meta:n = { scale-denominators = 0/#1 - 1/#1 }, timewarp .tl_set:N = \l__mermap_anim_timewarp_tl, timewarp-identity .meta:n = { timewarp = \mrcTimewarpIdentity }, timewarp-slow-start .meta:n = { timewarp = \mrcTimewarpSlowStart{#1} }, timewarp-slow-start .default:n = 2, timewarp-slow-final .meta:n = { timewarp = \mrcTimewarpSlowFinal{#1} }, timewarp-slow-final .default:n = 2, timewarp-slow-start-final .meta:n = { timewarp = \mrcTimewarpSlowStartFinal{#1} }, timewarp-slow-start-final .default:n = 2, } \keys_set:nn { mermap/anim } { position = 51.4779 / 0, frames = 20, drop-no-frame, common-scale-denominator = 25000, timewarp-identity, } \NewExpandableDocumentCommand\mrcAnimFrame {} { \int_to_arabic:n { \l_mermap_anim_frame_int }} \NewExpandableDocumentCommand\mrcAnimTime {} { \fp_to_decimal:N \l_mermap_anim_time_fp } \NewExpandableDocumentCommand\mrcAnimScaleDenom {} { \fp_to_decimal:N \l_mermap_anim_scaledenom_fp } \NewExpandableDocumentCommand\mrcAnimLatitude {} { \fp_to_decimal:N \l_mermap_anim_lat_fp } \NewExpandableDocumentCommand\mrcAnimLongitude {} { \fp_to_decimal:N \l_mermap_anim_lon_fp } \NewExpandableDocumentCommand\mrcAnimAngle {} { \fp_to_decimal:N \l_mermap_anim_angle_fp } %---- supplier ----------------------------------------------------------------- \file_input:n { \mrcpkgprefix mercatorsupplier.def }