%% The LaTeX package mercatormap - version 1.2.0 (2024/08/05) %% mercatormap.sty: geographic coordinates (Mercator projection) and map tiles for TikZ pictures %% %% ------------------------------------------------------------------------------------------- %% Copyright (c) 2020-2024 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}[2023-11-01] \ProvidesExplPackage{mercatormap}{2024/08/05}{1.2.0} {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 } %---- 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} \NewDocumentCommand\mrcmapattribution{}{\tl_use:N \l__mermap_attribution_tl} \NewDocumentCommand\mrcmapattributionprint{}{\tl_use:N \l__mermap_attribution_print_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} \cs_new_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[name=mrcmap,at={(0,0)},above~right, line~width=0mm,inner~sep=0mm,outer~sep=0mm,draw=none,fill=none,rectangle, minimum~width=\mrctexwidth,minimum~height=\mrctexheight]{}; } } \cs_new_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_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_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_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_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_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} } \use:x { \cs_new_nopar:Npn \exp_not:N\__mermap_pgfpoint:w ##1 \c_colon_str ##2 \exp_not:N \q_stop } { \__mermap_pgfpoint:nn {#1}{#2} } \cs_new_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_nopar:Npn \__mermap_set_named_position #1#2#3 { \cs_set_nopar:cpx {__mermap__lat__#1} { \fp_to_decimal:n {#2} } \cs_set_nopar:cpx {__mermap__lon__#1} { \fp_to_decimal:n {#3} } } \NewDocumentCommand{\mrcNPdef}{ mmm } { \__mermap_set_named_position{#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 {#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 {`\ } \char_set_catcode_other:n {`\"} \tl_const:Nn \c__mermap_supply_call_boundaries_tl { \l__mermap_python_tl\c_space_tl boundaries -u "\str_use:N\l__mermap_supply_url_str" -at "\str_use:N\l__mermap_supply_attribution_str" -atp "\str_use:N\l__mermap_supply_attribution_print_str" -f "\l__mermap_supply_basename_tl" -z \int_use:N\l__mermap_supply_zoom_int\c_space_tl -w \fp_use:N\l__mermap_supply_west_fp\c_space_tl -e \fp_use:N\l__mermap_supply_east_fp\c_space_tl -n \fp_use:N\l__mermap_supply_north_fp\c_space_tl -s \fp_use:N\l__mermap_supply_south_fp\c_space_tl -p \l__mermap_supply_pixel_tl\c_space_tl -ts \dim_use:N\l__mermap_tile_size_dim\c_space_tl -t \l__mermap_supply_target_tl\c_space_tl -d "\str_use:N\l__mermap_definition_id_str" } \tl_const:Nn \c__mermap_supply_call_reference_tl { \l__mermap_python_tl\c_space_tl reference -u "\str_use:N\l__mermap_supply_url_str" -at "\str_use:N\l__mermap_supply_attribution_str" -atp "\str_use:N\l__mermap_supply_attribution_print_str" -f "\l__mermap_supply_basename_tl" -mw \fp_use:N\l__mermap_supply_width_fp\c_space_tl -mh \fp_use:N\l__mermap_supply_height_fp\c_space_tl -z \int_use:N\l__mermap_supply_zoom_int\c_space_tl -lat \fp_use:N\l__mermap_supply_latitude_fp\c_space_tl -lon \fp_use:N\l__mermap_supply_longitude_fp\c_space_tl -a \l__mermap_supply_align_tl\c_space_tl -p \l__mermap_supply_pixel_tl\c_space_tl -ts \dim_use:N\l__mermap_tile_size_dim\c_space_tl -t \l__mermap_supply_target_tl\c_space_tl -d "\str_use:N\l__mermap_definition_id_str" } \tl_const:Nn \c__mermap_supply_call_areafit_tl { \l__mermap_python_tl\c_space_tl areafit -u "\str_use:N\l__mermap_supply_url_str" -at "\str_use:N\l__mermap_supply_attribution_str" -atp "\str_use:N\l__mermap_supply_attribution_print_str" -f "\l__mermap_supply_basename_tl" -mw \fp_use:N\l__mermap_supply_width_fp\c_space_tl -mh \fp_use:N\l__mermap_supply_height_fp\c_space_tl -w \fp_use:N\l__mermap_supply_west_fp\c_space_tl -e \fp_use:N\l__mermap_supply_east_fp\c_space_tl -n \fp_use:N\l__mermap_supply_north_fp\c_space_tl -s \fp_use:N\l__mermap_supply_south_fp\c_space_tl -a \l__mermap_supply_align_tl\c_space_tl -p \l__mermap_supply_pixel_tl\c_space_tl -ts \dim_use:N\l__mermap_tile_size_dim\c_space_tl -t \l__mermap_supply_target_tl\c_space_tl -d "\str_use:N\l__mermap_definition_id_str" } \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_iow \prop_new:N \g__mermap_apikey_prop \prop_new: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 \use:x { \cs_new_nopar:Npn \exp_not:N\__mermap_supply_position:w ##1 \c_colon_str ##2 \exp_not:N \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: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:nnx{ 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:Npn \__mermap_supply_add_area_clist:N #1 { \clist_map_inline:Nn #1 { \cs_if_exist:cF{__mermap__lat__##1} { \msg_error:nnx{ 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: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:Nx \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:Nx \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:Nnx \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=, attribution=, attribution~print=, type=reference, pixel=256, target=tiles, } \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:Nx \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:Npn \__mermap_create_definition_id:n #1 { \tl_set:Nx \l__mermap_tmpa_tl {#1} \tl_trim_spaces:N \l__mermap_tmpa_tl \str_set:Nx \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:Npn \__mermap_map:nn #1#2 { \tl_set:Nx \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:Nx \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:nNnTF \g__mermap_automap_int<{1000} {0} {} } } \int_use:N \g__mermap_automap_int } } \str_set:Nx \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 \__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:Npn \__mermap_supplymap:n #1 { \group_begin: \keys_set:nn { mermap/supply } { #1 } \tl_set:Nx \l__mermap_tmpa_tl { \str_use:N\l__mermap_definition_id_str } \prop_if_in:NVT \g__mermap_definition_prop \l__mermap_tmpa_tl { \msg_warning:nnx { mercatormap }{ definition-id-used }{ \tl_use:N \l__mermap_tmpa_tl } } \prop_gput:NVn \g__mermap_definition_prop \l__mermap_tmpa_tl {} \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:Npn \__mermap_supplymap_call: { \tl_set_eq:Nc \l__mermap_tmpa_tl { c__mermap_supply_call_\l__mermap_supply_type_tl _tl } \tl_set:Nx \l__mermap_supply_call_tl \l__mermap_tmpa_tl \tl_set:Nx \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: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_iow {\l__mermap_definition_id_str.def} \iow_now:Nx \l__mermap_iow {\c_backslash_str def \c_backslash_str mrcdefinemap{} \c_percent_str} \iow_close:N \l__mermap_iow } \sys_shell_now:x {\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:nnx { mercatormap }{ target-resource }{ \l__mermap_definition_id_str } } { \msg_warning:nnx { mercatormap }{ target-resource }{ \l__mermap_definition_id_str } } } } { \msg_error:nnx { mercatormap }{ definition-production }{ \l__mermap_definition_id_str } } } { \msg_error:nnx { mercatormap }{ shell-escape }{ \l__mermap_definition_id_str } } } \NewDocumentCommand \mermaplastfivesum { m } { \tl_set:Nx \l__mermap_last_mdfivesum_tl { #1 } } \cs_new:Npn \__mermap_write_mdfive:n #1 { \iow_open:Nn \l__mermap_iow {\l__mermap_definition_id_str.md5} \iow_now:Nx \l__mermap_iow {\c_backslash_str mermaplastfivesum{#1} \c_percent_str} \iow_close:N \l__mermap_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_current_map_tl \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_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 } } \use:x { \cs_new_nopar:Npn \exp_not:N\__mermap_set_flex_scale:w ##1 \c_colon_str ##2 \exp_not:N \q_stop } { \__mermap_set_flex_scale:nn {#1}{#2} } \use:x { \cs_new_nopar:Npn \exp_not:N\__mermap_set_named_flex_scale:w ##1 \c_colon_str ##2 \exp_not:N \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_nopar:Npn \__mermap_drawtile: { \tl_set:Nx \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_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: } } \msg_new:nnn{ mercatormap }{ draw-auto } { 'draw=auto' -> 'draw=#1'~is~undefined. } \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:nnx { 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:nnx { mercatormap }{ draw-undefined }{ \tl_use:N \l__mermap_draw_map_tl } } \group_end: } \cs_new_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_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_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} { \use:x { \exp_not:N\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_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_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_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_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:Nx \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:Nx \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:Nx \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:Nx \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 \tl_new:N \l__mermap_scalebar_position_tl \cs_new_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:Nx \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_nopar:Npn \__mermap_drawscalebar: { \use:x { \exp_not:N\node[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,rectangle, 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} % Breite \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:nnx{ 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_new:N \l__mermap_marker_use_urls \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 \use:x { \cs_new_nopar:Npn \exp_not:N\__mermap_marker_position:w ##1 \c_colon_str ##2 \exp_not:N \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, ignore~links .bool_set_inverse:N = \l__mermap_marker_use_links, use~urls .bool_set:N = \l__mermap_marker_use_urls, ignore~urls .bool_set_inverse:N = \l__mermap_marker_use_urls, 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, } \NewExpandableDocumentCommand\mrcmarkerlatitude{}{\fp_to_decimal:N \l__mermap_marker_latitude_fp} \NewExpandableDocumentCommand\mrcmarkerlongitude{}{\fp_to_decimal:N \l__mermap_marker_longitude_fp} \NewDocumentCommand\mrcmarkercontents{}{\tl_use:N \l__mermap_marker_contents_tl} \NewDocumentCommand\mrcmarkerpictocontents{}{\tl_use:N \l__mermap_marker_pictocontents_tl} \NewExpandableDocumentCommand\mrcmarkeruuid{}{\tl_use:N \l_mermap_marker_uuid_tl} \NewDocumentCommand\mrcmarkergeneric{}{\tl_use:N \l_mermap_marker_generic_tl} \NewExpandableDocumentCommand\mrcmarkercategory{}{\tl_use:N \l__mermap_marker_category_tl} \NewDocumentCommand\mrcmarkerfont{}{\tl_use:N \l__mermap_marker_font_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 { \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 { \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:nnx{ mercatormap }{ markertype-undefined }{ \l__mermap_marker_type_tl } } \end{scope} } } {} \group_end: } \cs_new: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:Nx \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:Nx \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_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_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_nopar:Npn \__mermap_pgf_moveto_point:nn #1#2 { \pgfpathmoveto{\__mermap_pgfpoint:nn {#1}{#2}} } \cs_new_nopar:Npn \__mermap_pgf_lineto_point:nn #1#2 { \pgfpathlineto{\__mermap_pgfpoint:nn {#1}{#2}} } \cs_new_nopar:Npn \__mermap_route_point #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_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 \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_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_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_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_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 { #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 { #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 { #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{ 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 }