From 36db81e567665da0b8e92831b69d2a71971312f3 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 20 Apr 2020 21:10:20 +0000 Subject: mercatormap (20apr20) git-svn-id: svn://tug.org/texlive/trunk@54812 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/latex/mercatormap/mercatormap.sty | 2294 ++++++++++++++++++++ .../tex/latex/mercatormap/mercatorpy.def | 535 +++++ .../tex/latex/mercatormap/mercatorsupplier.def | 290 +++ 3 files changed, 3119 insertions(+) create mode 100644 Master/texmf-dist/tex/latex/mercatormap/mercatormap.sty create mode 100644 Master/texmf-dist/tex/latex/mercatormap/mercatorpy.def create mode 100644 Master/texmf-dist/tex/latex/mercatormap/mercatorsupplier.def (limited to 'Master/texmf-dist/tex/latex/mercatormap') diff --git a/Master/texmf-dist/tex/latex/mercatormap/mercatormap.sty b/Master/texmf-dist/tex/latex/mercatormap/mercatormap.sty new file mode 100644 index 00000000000..d05872b77fe --- /dev/null +++ b/Master/texmf-dist/tex/latex/mercatormap/mercatormap.sty @@ -0,0 +1,2294 @@ +%% The LaTeX package mercatormap - version 1.00 (2020/04/20) +%% mercatormap.sty: geographic coordinates (Mercator projection) and map tiles for TikZ pictures +%% +%% ------------------------------------------------------------------------------------------- +%% Copyright (c) 2020 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 +%% +\RequirePackage{expl3}[2020/02/25] +\RequirePackage{xparse} +\ProvidesExplPackage{mercatormap}{2020/04/20}{1.00} + {A Web Mercator projection package with map tile support} +\@ifpackagelater { expl3 } { 2020/02/25 } + { } + { + \PackageError { mercatormap } { Support~package~expl3~too~old } + { + You~need~to~update~your~installation~of~the~bundles~'l3kernel'~and~ + 'l3packages'.\MessageBreak + Loading~mercatormap~will~abort! + } + \tex_endinput:D + } + +\RequirePackage{siunitx} +\RequirePackage{graphicx,tikz,pdftexcmds} + +\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} } + + +%---- 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_tmpa_fp { #1-\l__mermap_mapwest_fp } + \fp_sub:Nn \l_tmpa_fp { 360*floor(\l_tmpa_fp/360) } + \fp_set:Nn \l_tmpa_fp + { \l_tmpa_fp>\l__mermap_westeast_fp + ?(\l_tmpa_fp-\l__mermap_westeast_fp>360-\l_tmpa_fp + ?\l_tmpa_fp-360 + :\l_tmpa_fp) + :\l_tmpa_fp + } + \fp_set:Nn \l__mermap_cs_x_fp { \l_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, 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_tmpa_fp { #2-\l__mermap_mapwest_fp } + \fp_sub:Nn \l_tmpa_fp { 360*floor(\l_tmpa_fp/360) } + \fp_compare:nNnTF \l_tmpa_fp > \l__mermap_westeast_fp + { + \prg_return_false: + } + { + \fp_set:Nn \l__mermap_cs_x_fp { \l_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, 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_tmpa_fp { #2-\l__mermap_vic_west_fp } + \fp_sub:Nn \l_tmpa_fp { 360*floor(\l_tmpa_fp/360) } + \fp_compare:nNnTF \l_tmpa_fp > \l__mermap_vic_westeast_fp + { + \prg_return_false: + } + { + \fp_set:Nn \l__mermap_cs_x_fp { \l_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} + { + \msg_error:nnx{ mercatormap }{ np-undefined }{ #1 } + } + } + + +\NewExpandableDocumentCommand \mrcNPlon { m } + { + \cs_if_exist_use:cF{__mermap__lon__#1} + { + \msg_error:nnx{ mercatormap }{ np-undefined }{ #1 } + } + } + + +\NewExpandableDocumentCommand \mrcNPcs { m } + { + __mrc~cs \c_colon_str {{\mrcNPlat{#1}}{\mrcNPlon{#1}}} + } + + +\NewDocumentCommand{\ifmrcNPinmap}{ m } + { + \__mermap_if_in_map:nnTF{\mrcNPlat{#1}}{\mrcNPlon{#1}} + } + + +\NewDocumentCommand{\ifmrcNPinvicinity}{ m } + { + \__mermap_if_in_vicinity:nnTF{\mrcNPlat{#1}}{\mrcNPlon{#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\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\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\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 + +\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_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_tmpa_tl + { + \msg_error:nnx{ mercatormap }{ api-key-undefined }{ #2 } + } + \str_put_right:NV \l__mermap_supply_url_str \l_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_tmpa_fp { \mrcNPlat{##1} } + \fp_compare:nNnT \l_tmpa_fp < \l__mermap_supply_south_fp + { \fp_set_eq:NN \l__mermap_supply_south_fp \l_tmpa_fp } + \fp_compare:nNnT \l_tmpa_fp > \l__mermap_supply_north_fp + { \fp_set_eq:NN \l__mermap_supply_north_fp \l_tmpa_fp } + \fp_set:Nn \l_tmpa_fp { \mrcNPlon{##1} } + \fp_compare:nNnT \l_tmpa_fp < \l__mermap_supply_west_fp + { \fp_set_eq:NN \l__mermap_supply_west_fp \l_tmpa_fp } + \fp_compare:nNnT \l_tmpa_fp > \l__mermap_supply_east_fp + { \fp_set_eq:NN \l__mermap_supply_east_fp \l_tmpa_fp } + } + } + + +\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_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_tmpa_clist + }, + area .value_required:n = true, + add~area .code:n = + { + \clist_set:Nn \l_tmpa_clist { #1 } + \__mermap_supply_add_area_clist:N \l_tmpa_clist + }, + 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_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_tmpa_fp} + \fp_set:Nn \l__mermap_supply_height_fp{\l__mermap_supply_height_fp*\l_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_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_tmpb_fp { ln(\l_tmpa_fp)/ln(2) } + \fp_set:Nn \l_tmpb_fp { round(\l_tmpb_fp)/\l_tmpb_fp } + \fp_set:Nn \l_tmpb_fp { \l_tmpa_fp^(\l_tmpb_fp-1+0.0000001) } + \dim_set:Nn \l__mermap_tile_size_dim { \fp_to_dim:n { \l__mermap_flex_tile_size_dim / \l_tmpb_fp }} + \fp_set:Nn \l__mermap_supply_width_fp { \l__mermap_supply_width_fp * \l_tmpb_fp + (#1)/\l__mermap_tile_size_dim } + \fp_set:Nn \l__mermap_supply_height_fp { \l__mermap_supply_height_fp * \l_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}}, + python .code:n = { + \tl_set:Nx \l__mermap_python {#1~maptiles.texpy} + }, + } + +\keys_set:nn { mermap } + { + definition~prefix = maps/, + 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 } + \group_begin: + \def\@latex@warning@no@line##1{}% suppress filecontents warning + \file_input:n {\mrcpkgprefix mercatorpy.def} + \group_end: + \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_tmpa_tl {#1} + \tl_trim_spaces:N \l_tmpa_tl + \str_set:Nx \l__mermap_definition_postfix_str {\tl_to_str:N \l_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_tmpa_tl {#2} + \tl_trim_spaces:N \l_tmpa_tl + \tl_if_empty:NT \l_tmpa_tl + { + \int_gincr:N \g__mermap_automap_int + \tl_set:Nx \l_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_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_tmpa_tl { \str_use:N\l__mermap_definition_id_str } + \prop_if_in:NVT \g__mermap_definition_prop \l_tmpa_tl + { + \msg_warning:nnx { mercatormap }{ definition-id-used }{ \tl_use:N \l_tmpa_tl } + } + \prop_gput:NVn \g__mermap_definition_prop \l_tmpa_tl {} + \bool_if:NT \l__mermap_script_activated_bool + { + \__mermap_supplymap_call: + } + %\dim_gset_eq:NN \g_tmpa_dim \l__mermap_tile_size_dim + \group_end: + %\dim_set_eq:NN \l__mermap_tile_size_dim \g_tmpa_dim + } + +\NewDocumentCommand \mrcsupplymap { O{} m } + { + \__mermap_create_definition_id:n {#2} + \__mermap_supplymap:n {#1} + } + + +\msg_new:nnn { mercatormap }{ shell-escape } + { You~must~invoke~LaTeX~with~the~--shell-escape~flag~to~produce~map~'#1'. } + +\msg_new:nnn { mercatormap }{ target-resource } + { Target~and~produced~resource~are~different~for~map~'#1'. } + +\msg_new:nnn { mercatormap }{ definition-production } + { Map~definition~file~not~produced~for~map~'#1'. } + +\cs_new:Npn \__mermap_supplymap_call: + { + \tl_set_eq:Nc \l_tmpa_tl { + c__mermap_supply_call_\l__mermap_supply_type_tl _tl } + \tl_set:Nx \l__mermap_supply_call_tl \l_tmpa_tl + \tl_set:Nx \l__mermap_mdfivesum_tl { \pdf@mdfivesum{\l__mermap_supply_call_tl} } + \tl_clear:N \l__mermap_last_mdfivesum_tl + \file_if_exist_input:n {\l__mermap_definition_id_str.md5} + \str_if_eq:VVTF \l__mermap_mdfivesum_tl \l__mermap_last_mdfivesum_tl + { + \file_if_exist:nF {\l__mermap_definition_id_str.def} + { + \__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} + \msg_warning:nnx { mercatormap }{ target-resource }{ \l__mermap_definition_id_str } + } + } + { + \__mermap_write_mdfive:n {false} + \msg_warning:nnx { mercatormap }{ definition-production }{ \l__mermap_definition_id_str } + } + } + { + \__mermap_write_mdfive:n {false} + \msg_warning: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_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_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_tmpa_fp + { + min ( \l__mermap_network_pieces_int, round((#1)/\l__mermap_network_distance_dim) ) + } + \fp_set:Nn \l_tmpb_fp { (#2)/\l_tmpa_fp } + \fp_set:Nn \l_tmpa_fp { floor(ln(\l_tmpb_fp)/ln(10)) } + \fp_compare:nNnTF {\l_tmpa_fp} < {0} + { + \fp_compare:nNnTF {\l_tmpa_fp} > {-5} + { + \use:x + { + \exp_not:N\keys_set:nn { mermap }{ format~angle=decimal\fp_to_int:N\l_tmpa_fp} + } + } + { + \keys_set:nn { mermap }{ format~angle=decimal } + } + } + { + \keys_set:nn { mermap }{ format~angle=decimal-0 } + } + \fp_set:Nn \l_tmpa_fp { 10^\l_tmpa_fp } + \fp_set:Nn \l_tmpb_fp { \l_tmpb_fp/\l_tmpa_fp } + \fp_compare:nNnTF {abs(\l_tmpb_fp-1)} < {abs(\l_tmpb_fp-2)} + { + \fp_compare:nNnTF {abs(\l_tmpb_fp-1)} < {abs(\l_tmpb_fp-5)} + { + \fp_set:Nn \l__mermap_result_fp {\l_tmpa_fp} + } + { + \fp_set:Nn \l__mermap_result_fp {5*\l_tmpa_fp} + } + } + { + \fp_compare:nNnTF {abs(\l_tmpb_fp-2)} < {abs(\l_tmpb_fp-5)} + { + \fp_set:Nn \l__mermap_result_fp {2*\l_tmpa_fp} + } + { + \fp_set:Nn \l__mermap_result_fp {5*\l_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_tmpa_fp { ceil(\l__mermap_mapsouth_fp/\l__mermap_result_fp)*\l__mermap_result_fp} + \fp_compare:nNnT {\l_tmpa_fp-\l__mermap_mapsouth_fp} < {1e-10} + { + \fp_add:Nn \l_tmpa_fp {\l__mermap_result_fp} + } + \fp_while_do:nNnn {\l_tmpa_fp} < {\l__mermap_mapnorth_fp} + { + \tl_set:Nn \l_tmpa_tl {\fp_use:N\l_tmpa_fp} + \draw[gray,very~thin] (mrc~cs\c_colon_str lat=\l_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_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_tmpa_tl}} + ; + \fp_add:Nn \l_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_tmpa_fp { ceil(\l__mermap_mapwest_fp/\l__mermap_result_fp)*\l__mermap_result_fp} + \fp_compare:nNnT {\l_tmpa_fp-\l__mermap_mapwest_fp} < {1e-10} + { + \fp_add:Nn \l_tmpa_fp {\l__mermap_result_fp} + } + \fp_while_do:nNnn {\l_tmpa_fp} < {\l__mermap_mapeast_fp} + { + \tl_set:Nn \l_tmpa_tl {\fp_use:N\l_tmpa_fp} + \draw[gray,very~thin] (mrc~cs\c_colon_str lon=\l_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_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_tmpa_tl}} + ; + \fp_add:Nn \l_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_tmpa_fp { #1 } + \fp_compare:nNnTF \l_tmpa_fp < 5 + { + \SI[round-mode=figures,round-precision=3,detect-all]{\fp_to_decimal:n{1000*\l_tmpa_fp}}{\meter} + } + { + \SI[round-mode=figures,round-precision=3,detect-all]{\fp_to_decimal:N \l_tmpa_fp}{\kilo\meter} + } + } + + +\cs_new_nopar:Npn \__mermap_pretty_length:n #1 + { + \fp_set:Nn \l_tmpa_fp { (#1)*\l__mermap_scale_fp } + \fp_compare:nNnTF \l_tmpa_fp < 5 + { + \SI[round-mode=figures,round-precision=3,detect-all]{\fp_to_decimal:n{1000*\l_tmpa_fp}}{\meter} + } + { + \SI[round-mode=figures,round-precision=3,detect-all]{\fp_to_decimal:N \l_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_tmpa_fp {floor(#1)} + \fp_set:Nn \l_tmpb_fp {round((#1-\l_tmpa_fp)*60)} + \ang[add-arc-degree-zero,add-arc-minute-zero] + { + \fp_to_int:N \l_tmpa_fp ; + \fp_to_int:N \l_tmpb_fp ; + } + } + + +\cs_new_nopar:Npn \__mermap_format_angle_second:n #1 + { + \fp_set:Nn \l_tmpa_fp {floor(#1)} + \fp_set:Nn \l_tmpb_fp {floor((#1-\l_tmpa_fp)*60)} + \ang[add-arc-degree-zero,add-arc-minute-zero] + { + \fp_to_int:N \l_tmpa_fp ; + \fp_to_int:N \l_tmpb_fp ; + \fp_to_int:n {round(((#1-\l_tmpa_fp)*60-\l_tmpb_fp)*60)} + } + } + +\NewDocumentCommand{\mrcformlat}{ o m } + { + \group_begin: + \IfNoValueF {#1} + { \keys_set:nn { mermap } {#1} } + \fp_set:Nn \l_tmpa_fp {#2} + \fp_compare:nNnTF \l_tmpa_fp < 0 + { + \tl_set:Nx \l__mermap_temp_tl {\fp_to_decimal:n{-\l_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_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_tmpa_fp {#2-360*floor((#2+180)/360)} + \fp_compare:nNnTF \l_tmpa_fp < 0 + { + \tl_set:Nx \l__mermap_temp_tl {\fp_to_decimal:n{-\l_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_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_tmpa_fp {0} + \fp_set:Nn \l_tmpb_fp {0} + } + { + \fp_set:Nn \l_tmpa_fp {#3*(#5)} + \tl_if_empty:nTF {#6} + { + \fp_set:Nn \l_tmpb_fp {#4*(#5)} + } + { + \fp_set:Nn \l_tmpb_fp {#4*(#6)} + } + } + \tl_set:Nx \l__mermap_scalebar_at_tl + { + {([xshift=\fp_to_dim:N\l_tmpa_fp,yshift=\fp_to_dim:N\l_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 = {([xshift=-10mm,yshift=5mm]mrcmap.south~east)}, + %placement = above~left, + 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_tmpa_fp {\l__mermap_scalebar_width_fp/\l__mermap_scale_fp} % Breite + \pgfpathrectangle{\pgfpoint{0pt}{0pt}} + {\pgfpoint{\fp_to_dim:N\l_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_tmpa_fp {\l__mermap_scalebar_width_fp/\l__mermap_scale_fp} + } + \fp_set:Nn \l_tmpb_fp {\l_tmpa_fp/\l__mermap_scalebar_partitions_int} + \bool_if:NTF \l__mermap_scalebar_double_bool + { + \int_set:Nn \l_tmpa_int {1} + \dim_set:Nn \l_tmpb_dim {\l__mermap_scalebar_height_dim/2} + \dim_set:Nn \l_tmpa_dim {0.2pt-\l_tmpb_dim} + \int_compare:nNnTF \l__mermap_scalebar_partitions_int = 1 + { + \pgfpathrectangle{\pgfpoint{0.2pt}{\l_tmpb_dim}} + {\pgfpoint{\fp_to_dim:n{\l_tmpb_fp-0.4pt}}{\l_tmpa_dim}} + } + { + \pgfpathrectangle{\pgfpoint{0.2pt}{\l_tmpb_dim}} + {\pgfpoint{\fp_to_dim:n{\l_tmpb_fp-0.2pt}}{\l_tmpa_dim}} + } + \int_while_do:nNnn \l_tmpa_int < \l__mermap_scalebar_partitions_int + { + \dim_set:Nn \l_tmpa_dim {-\l_tmpa_dim} + \int_compare:nNnTF {\l_tmpa_int+1} = \l__mermap_scalebar_partitions_int + { + \pgfpathrectangle{\pgfpoint{\fp_to_dim:n{\l_tmpa_int*\l_tmpb_fp}}{\l_tmpb_dim}} + {\pgfpoint{\fp_to_dim:n{\l_tmpb_fp-0.2pt}}{\l_tmpa_dim}} + } + { + \pgfpathrectangle{\pgfpoint{\fp_to_dim:n{\l_tmpa_int*\l_tmpb_fp}}{\l_tmpb_dim}} + {\pgfpoint{\fp_to_dim:N\l_tmpb_fp}{\l_tmpa_dim}} + } + \int_incr:N \l_tmpa_int + } + } + { + \int_set:Nn \l_tmpa_int {1} + \dim_set:Nn \l_tmpa_dim {\l__mermap_scalebar_height_dim-0.4pt} + \int_while_do:nNnn \l_tmpa_int < \l__mermap_scalebar_partitions_int + { + \int_compare:nNnTF {\l_tmpa_int+1} = \l__mermap_scalebar_partitions_int + { + \pgfpathrectangle{\pgfpoint{\fp_to_dim:n{\l_tmpa_int*\l_tmpb_fp}}{0.2pt}} + {\pgfpoint{\fp_to_dim:n{\l_tmpb_fp-0.2pt}}{\l_tmpa_dim}} + } + { + \pgfpathrectangle{\pgfpoint{\fp_to_dim:n{\l_tmpa_int*\l_tmpb_fp}}{0.2pt}} + {\pgfpoint{\fp_to_dim:N\l_tmpb_fp}{\l_tmpa_dim}} + } + \int_add:Nn \l_tmpa_int {2} + } + } + \__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 + +\fp_new:N \l__mermap_marker_angle_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_pictocontents_tl +\tl_new:N \l__mermap_marker_type_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, + % name .meta:nn = {mermap/marker}{contents={#1},alias={#1}}, + uuid .tl_set:N = \l__mermap_marker_uuid_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, + 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} }, + 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, + % name = noname, + contents =, + alias = noname, + pictocontents =, + angle = 90, + shift = 0pt, + fill = gray!20, + draw = gray, + text = black, + radius = 3mm, + inner~radius = 2.25mm, + path~style =, + node~style =, + font = \sffamily\small, + type = classic, + uuid =, + category =, + show = 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} +\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\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. + } + + +\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]\mrcmarkercontents}] {}; + } + +\__mermap_new_marker_type:nn {pin} + { + \path[fill=mrcmarkerfill,draw=none,fill~opacity=0.7] + (0,0) -- (0.1,0.5) -- (-0.1,0.5) -- 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] + (pin_node) at (0,0.5) {\mrcmarkercontents}; + \path[draw=mrcmarkerdraw,fill=none,line~join=round,mrcpathstyle] + (0,0) -- (0.1,0.5) -- (pin_node.south~east) -- (pin_node.north~east) + -- (pin_node.north~west) -- (pin_node.south~west) + -- (-0.1,0.5) [line~join=bevel] -- cycle; + } + +\__mermap_new_marker_type:nn {pinflip} + { + \path[fill=mrcmarkerfill,draw=none,fill~opacity=0.7] + (0,0) -- (-0.1,-0.5) -- (0.1,-0.5) -- 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] + (pin_node) at (0,-0.5) {\mrcmarkercontents}; + \path[draw=mrcmarkerdraw,fill=none,line~join=round,mrcpathstyle] + (0,0) -- (-0.1,-0.5) -- (pin_node.north~west) -- (pin_node.south~west) + -- (pin_node.south~east) -- (pin_node.north~east) + -- (0.1,-0.5) [line~join=bevel] -- cycle; + } + + +\cs_new_nopar:Npn \__mermap_tikz_drop_path:n #1 + { + \tl_set:Nn \l_tmpa_tl {\fp_to_dim:N\l__mermap_marker_radius_fp} + \tl_set:Nn \l_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 + } + \pgfpathmoveto{\pgfpoint{0pt}{\fp_to_dim:n{-2*\l__mermap_marker_radius_fp-\l__mermap_marker_shift_fp}}} + \pgfpathcurveto{\pgfpoint{\l_tmpb_tl}{-\l_tmpa_tl}}{\pgfpoint{\l_tmpa_tl}{-\l_tmpb_tl}} + {\pgfpoint{\l_tmpa_tl}{0pt}} + \pgfpathcurveto{\pgfpoint{\l_tmpa_tl}{\l_tmpb_tl}}{\pgfpoint{\l_tmpb_tl}{\l_tmpa_tl}} + {\pgfpoint{0pt}{\l_tmpa_tl}} + \pgfpathcurveto{\pgfpoint{-\l_tmpb_tl}{\l_tmpa_tl}}{\pgfpoint{-\l_tmpa_tl}{\l_tmpb_tl}} + {\pgfpoint{-\l_tmpa_tl}{0pt}} + \pgfpathcurveto{\pgfpoint{-\l_tmpa_tl}{-\l_tmpb_tl}}{\pgfpoint{-\l_tmpb_tl}{-\l_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_tmpa_box {\mrcmarkercontents} + \fp_compare:nNnT {\box_wd:N \l_tmpa_box} > {1.5*\l__mermap_marker_radius_fp} + { + \box_resize_to_wd_and_ht:Nnn \l_tmpa_box + {\fp_to_dim:n {1.5*\l__mermap_marker_radius_fp}} + {\box_ht:N \l_tmpa_box} + } + \box_use_drop:N \l_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] + 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] + 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,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_tmpa_tl {\fp_to_dim:N\l__mermap_marker_radius_fp} + \path[draw=mrcmarkerdraw,very~thin] + (45 \c_colon_str \l_tmpa_tl)--(225\c_colon_str \l_tmpa_tl) + (135\c_colon_str \l_tmpa_tl)--(315\c_colon_str \l_tmpa_tl); + \path[draw=mrcmarkerdraw,fill=mrcmarkerfill,mrcpathstyle,even~odd~rule] + circle (\l_tmpa_tl) circle (\fp_to_dim:N\l__mermap_marker_inner_radius_fp); + } + +\__mermap_new_marker_type:nn {markx} + { + \tl_set:Nn \l_tmpa_tl {\fp_to_dim:N\l__mermap_marker_radius_fp} + \path[line~join=bevel,draw=mrcmarkerdraw,fill=mrcmarkerfill,mrcpathstyle] + (0,0) -- (35 \c_colon_str \l_tmpa_tl) -- (55 \c_colon_str \l_tmpa_tl) -- cycle + (0,0) -- (125 \c_colon_str \l_tmpa_tl) -- (145 \c_colon_str \l_tmpa_tl) -- cycle + (0,0) -- (215 \c_colon_str \l_tmpa_tl) -- (235 \c_colon_str \l_tmpa_tl) -- cycle + (0,0) -- (305 \c_colon_str \l_tmpa_tl) -- (325 \c_colon_str \l_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_delta_lambda_fp +\fp_new:N \l__mermap_delta_phi_fp +\fp_new:N \l__mermap_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 + +\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:Npn \__mermap_draw_orthodrome:nnnnn #1#2#3#4#5 + { + \__mermap_tikz_path_begin:n { draw,mermap_every_route,#1 } + \fp_set:Nn \l__mermap_a_x_fp { cosd(#3)*cosd(#2) } + \fp_set:Nn \l__mermap_a_y_fp { sind(#3)*cosd(#2) } + \fp_set:Nn \l__mermap_a_z_fp { sind(#2) } + \fp_set:Nn \l__mermap_b_x_fp { cosd(#5)*cosd(#4) } + \fp_set:Nn \l__mermap_b_y_fp { sind(#5)*cosd(#4) } + \fp_set:Nn \l__mermap_b_z_fp { sind(#4) } + + \fp_set:Nn \l_tmpa_fp { sind(#2)*sind(#4) + cosd(#2)*cosd(#4)*cosd(#5-(#3)) } + \fp_set:Nn \l__mermap_psi_fp { acosd(\l_tmpa_fp) } + \fp_set:Nn \l_tmpb_fp { sind(\l__mermap_psi_fp) } + + \fp_set:Nn \l__mermap_b_x_fp { (\l__mermap_b_x_fp - \l_tmpa_fp*\l__mermap_a_x_fp)/\l_tmpb_fp } + \fp_set:Nn \l__mermap_b_y_fp { (\l__mermap_b_y_fp - \l_tmpa_fp*\l__mermap_a_y_fp)/\l_tmpb_fp } + \fp_set:Nn \l__mermap_b_z_fp { (\l__mermap_b_z_fp - \l_tmpa_fp*\l__mermap_a_z_fp)/\l_tmpb_fp } + + \__mermap_pgf_moveto_point:nn {#2}{#3} + \int_set:Nn \l_tmpa_int {1} + \int_until_do:nNnn \l_tmpa_int > \l__mermap_samples_int + { + \fp_set:Nn \l_tmpa_fp { \l__mermap_psi_fp*\l_tmpa_int/\l__mermap_samples_int } + \fp_set:Nn \l_tmpb_fp { sind(\l_tmpa_fp) } + \fp_set:Nn \l_tmpa_fp { cosd(\l_tmpa_fp) } + \fp_set:Nn \l__mermap_t_x_fp { \l_tmpa_fp*\l__mermap_a_x_fp + \l_tmpb_fp*\l__mermap_b_x_fp } + \fp_set:Nn \l__mermap_t_y_fp { \l_tmpa_fp*\l__mermap_a_y_fp + \l_tmpb_fp*\l__mermap_b_y_fp } + \fp_set:Nn \l__mermap_t_z_fp { \l_tmpa_fp*\l__mermap_a_z_fp + \l_tmpb_fp*\l__mermap_b_z_fp } + \pgfpathlineto{\__mermap_unit_sphere_point:nnn {\l__mermap_t_x_fp}{\l__mermap_t_y_fp}{\l__mermap_t_z_fp}} + \int_incr:N \l_tmpa_int + } + \__mermap_tikz_path_end: + } + + +\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_tmpa_fp { tand(#1) } + \fp_set:Nn \l_tmpb_fp { \l__mermap_delta_lambda_fp*cosd(#1) + /( 1 + (\l_tmpa_fp + (1+2*\l_tmpa_fp*\l_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_tmpb_fp*\l_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 } + } + + + +%---- supplier ----------------------------------------------------------------- + +\file_input:n { \mrcpkgprefix mercatorsupplier.def } diff --git a/Master/texmf-dist/tex/latex/mercatormap/mercatorpy.def b/Master/texmf-dist/tex/latex/mercatormap/mercatorpy.def new file mode 100644 index 00000000000..fe608f47b49 --- /dev/null +++ b/Master/texmf-dist/tex/latex/mercatormap/mercatorpy.def @@ -0,0 +1,535 @@ +\begin{filecontents*}[overwrite]{maptiles.texpy} +""" +The LaTeX package mercatormap - version 1.00 (2020/04/20) +maptiles.texpy: Python script for map tile download + +------------------------------------------------------------------------------------------- +Copyright (c) 2020 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 +""" + +import argparse +import math +import os +import requests +from pathlib import Path +from PIL import Image + + +packageversion = '1.00 (2020/04/20)' + + +def gd(x): + return math.atan(math.sinh(x)) + + +def arggd(x): + return math.asinh(math.tan(x)) + + +def rad2planar(lon_rad, lat_rad): + x = 0.5*lon_rad/math.pi + 0.5 + y = 0.5*arggd(lat_rad)/math.pi + 0.5 + return (x, y) + + +def deg2planar(lon_deg, lat_deg): + return rad2planar(math.radians(lon_deg), math.radians(lat_deg)) + + +def planar2rad(x, y): + lon_rad = math.pi*(2*x-1) + lat_rad = gd(math.pi*(2*y-1)) + return (lon_rad, lat_rad) + + +def planar2deg(x, y): + (lon_rad, lat_rad) = planar2rad(x, y) + return (math.degrees(lon_rad), math.degrees(lat_rad)) + + +def download(session, url, filename, overwrite=False): + local_file = Path(filename) + if local_file.is_file() and not overwrite: + return + print(url+' -> '+filename) + r = session.get(url) + r.raise_for_status() + with open(filename, 'wb') as handler: + handler.write(r.content) + return + + +def makeparentdirs(afile): + directory = Path(os.path.abspath(afile)).parent + if not directory.is_dir(): + os.makedirs(directory) + + +class MapDefinition(object): + def __init__(self, args, west, east, north, south, zoom, x_1, y_1, x_2, y_2, + width, height, west_offset, north_offset, south_offset): + self.west = west + self.east = east + self.north = north + self.south = south + self.zoom = zoom + self.x_1 = x_1 + self.y_1 = y_1 + self.x_2 = x_2 + self.y_2 = y_2 + self.width = width + self.height= height + self.west_offset = west_offset + self.north_offset = north_offset + self.south_offset = south_offset + self.n = 2 ** self.zoom + self.local_file_prefix = 'tiles/tile_' + self.attribution = args.attribution + self.attributionprint = args.attributionprint + self.pixel = args.pixel + self.pixel_width = round(self.width*self.pixel) + self.pixel_height = round(self.height*self.pixel) + self.tilesize = args.tilesize + + + @classmethod + def construct_from_boundaries_rad(cls, args, zoom, west_rad, east_rad, north_rad, south_rad): + if zoom<0: + zoom = 0 + if west_rad>=east_rad: + east_rad += 2*math.pi*math.ceil(0.5*(west_rad-east_rad)/math.pi+1e-10) + max_lat = gd(math.pi)-1e-10 + if north_rad max_lat: + north_rad = max_lat + if south_rad < -max_lat: + south_rad = -max_lat + P = 2**(zoom-1)/math.pi + a1 = (west_rad+math.pi)*P + b1 = (math.pi-arggd(north_rad))*P + a2 = (east_rad+math.pi)*P + b2 = (math.pi-arggd(south_rad))*P + x1 = math.floor(a1) + y1 = math.floor(b1) + x2 = math.ceil(a2)-1 + y2 = math.ceil(b2)-1 + width = a2-a1 + height = b2-b1 + west_offset = a1-x1 + north_offset = b1-y1 + south_offset = y2-b2+1 + return cls(args, west_rad, east_rad, north_rad, south_rad, zoom, x1, y1, x2, y2, + width, height, west_offset, north_offset, south_offset ) + + + @classmethod + def construct_from_boundaries_deg(cls, args, zoom, west_deg, east_deg, north_deg, south_deg): + return cls.construct_from_boundaries_rad(args, + zoom,math.radians(west_deg),math.radians(east_deg), + math.radians(north_deg),math.radians(south_deg)) + + + @classmethod + def construct_from_boundaries_args(cls, args): + return cls.construct_from_boundaries_rad(args, + args.zoom,math.radians(args.west),math.radians(args.east),math.radians(args.north),math.radians(args.south)) + + + @classmethod + def construct_from_reference_rad(cls, args, zoom, width, height, + ref_lon_rad, ref_lat_rad, xalign, yalign): + if zoom<0: + zoom = 0 + P = 2**(zoom-1)/math.pi + ac = (ref_lon_rad+math.pi)*P + bc = (math.pi-arggd(ref_lat_rad))*P + a1 = ac - (1+xalign)/2*width + a2 = a1 + width + b1 = bc - (1+yalign)/2*height + b2 = b1 + height + west_rad = a1/P - math.pi + north_rad = gd(math.pi-b1/P) + east_rad = a2/P - math.pi + south_rad = gd(math.pi-b2/P) + x1 = math.floor(a1) + y1 = math.floor(b1) + x2 = math.ceil(a2)-1 + y2 = math.ceil(b2)-1 + west_offset = a1-x1 + north_offset = b1-y1 + south_offset = y2-b2+1 + return cls(args, west_rad, east_rad, north_rad, south_rad, zoom, x1, y1, x2, y2, + width, height, west_offset, north_offset, south_offset ) + + + @classmethod + def construct_from_reference_deg(cls, args, zoom, width, height, + ref_lon_deg, ref_lat_deg, xalign, yalign): + return cls.construct_from_center_rad(args, zoom, width, height, + math.radians(ref_lon_deg), math.radians(ref_lat_deg), xalign, yalign) + + + @classmethod + def construct_from_reference_args(cls, args): + return cls.construct_from_reference_rad(args, args.zoom, args.width, args.height, + math.radians(args.longitude), math.radians(args.latitude), args.xalign, args.yalign) + + + @classmethod + def construct_to_fit_region_rad(cls, args, width, height, reg_west_rad, reg_east_rad, + reg_north_rad, reg_south_rad, xalign, yalign): + if reg_west_rad>=reg_east_rad: + reg_east_rad += 2*math.pi*math.ceil(0.5*(reg_west_rad-reg_east_rad)/math.pi+1e-10) + max_lat = gd(math.pi)-1e-10 + if reg_north_rad max_lat: + reg_north_rad = max_lat + if reg_south_rad < -max_lat: + reg_south_rad = -max_lat + zoom = max( 0, 1 + math.floor( math.log2( math.pi * + min( width/(reg_east_rad-reg_west_rad), height/(arggd(reg_north_rad)-arggd(reg_south_rad))) + ))) + P = 2**(zoom-1)/math.pi + + if xalign<0: + a1 = (reg_west_rad+math.pi)*P + a2 = a1 + width + elif xalign>0: + a2 = (reg_east_rad+math.pi)*P + a1 = a2 - width + else: + a1 = ((reg_west_rad+reg_east_rad)/2+math.pi)*P - width/2 + a2 = a1 + width + + if yalign<0: + b1 = (math.pi-arggd(reg_north_rad))*P + b2 = b1 + height + elif yalign>0: + b2 = (math.pi-arggd(reg_south_rad))*P + b1 = b2 - height + else: + b1 = (math.pi-(arggd(reg_north_rad)+arggd(reg_south_rad))/2)*P - height/2 + b2 = b1 + height + west_rad = a1/P - math.pi + north_rad = gd(math.pi-b1/P) + east_rad = a2/P - math.pi + south_rad = gd(math.pi-b2/P) + x1 = math.floor(a1) + y1 = math.floor(b1) + x2 = math.ceil(a2)-1 + y2 = math.ceil(b2)-1 + west_offset = a1-x1 + north_offset = b1-y1 + south_offset = y2-b2+1 + return cls(args, west_rad, east_rad, north_rad, south_rad, zoom, x1, y1, x2, y2, + width, height, west_offset, north_offset, south_offset ) + + + @classmethod + def construct_to_fit_region_deg(cls, args, width, height, + reg_west_deg, reg_east_deg, reg_north_deg, reg_south_deg, + xalign, yalign): + return cls.construct_to_fit_region_rad(args, width, height, + math.radians(reg_west_deg),math.radians(reg_east_deg), + math.radians(reg_north_deg),math.radians(reg_south_deg), + xalign, yalign) + + + @classmethod + def construct_to_fit_region_args(cls, args): + return cls.construct_to_fit_region_rad(args, args.width, args.height, + math.radians(args.west),math.radians(args.east), + math.radians(args.north),math.radians(args.south), + args.xalign, args.yalign) + + + def get_tile_quantity(self): + return (self.x_2-self.x_1+1)*(self.y_2-self.y_1+1) + + + def get_pixel_quantity(self): + return self.pixel_width*self.pixel_height + + + def download_tiles(self, url_format, local_file_prefix): + self.local_file_prefix = local_file_prefix + makeparentdirs(local_file_prefix) + with requests.Session() as s: + s.headers.update(dict(referer = 'mercatormap/'+packageversion)) + try: + for xx in range(self.x_1, self.x_2+1): + x = xx % self.n + for y in range(self.y_1, self.y_2+1): + if (y>=0) and (y=0) and (y0: + if args.url!=None: + if target<3: + if mapdef.get_tile_quantity()>400: + if args.confirm: + tiles_success = mapdef.download_tiles(args.url, args.fileprefix) + else: + print(f'Too many tiles ({mapdef.get_tile_quantity()}). Add confirm option to proceed anyway.'); + else: + tiles_success = mapdef.download_tiles(args.url, args.fileprefix) + if tiles_success: + print('** Download of tiles successful for', args.definition) + if target>1: + merge_success = mapdef.merge_map(args.definition, args.fileprefix) + if merge_success: + print('** Merging tiles successful for', args.definition) + else: + print('** WARNING: Merging tiles failed for', args.definition) + else: + print('** WARNING: Map tiles download failed for', args.definition) + else: + if mapdef.get_pixel_quantity()>100000000: + if args.confirm: + wms_success = mapdef.download_wms_map(args.url, args.definition) + else: + print(f'Too many pixels ({mapdef.get_pixel_quantity()}). Add confirm option to proceed anyway.'); + else: + wms_success = mapdef.download_wms_map(args.url, args.definition) + else: + print('No url for download given') + + mapdef.save_map(args.definition, tiles_success, merge_success, wms_success) +\end{filecontents*} + diff --git a/Master/texmf-dist/tex/latex/mercatormap/mercatorsupplier.def b/Master/texmf-dist/tex/latex/mercatormap/mercatorsupplier.def new file mode 100644 index 00000000000..438374ba26f --- /dev/null +++ b/Master/texmf-dist/tex/latex/mercatormap/mercatorsupplier.def @@ -0,0 +1,290 @@ +%% The LaTeX package mercatormap - version 1.00 (2020/04/20) +%% mercatorsupplier.def: predefined map supplier list +%% +%% ------------------------------------------------------------------------------------------- +%% Copyright (c) 2020 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 +%% + +\NewDocumentCommand\mrcumlaut{m}{\"{#1}} + +\cs_new:Npn \__mermap_new_supply_source:nn #1#2 + { + \keys_define:nn { mermap/supply/_source } + { + #1 .meta:nn = {mermap/supply}{#2} + } + } + +\NewDocumentCommand\mrcnewsupplysource {mm} { + \__mermap_new_supply_source:nn {#1}{#2} +} + +\__mermap_new_supply_source:nn { dummy } + { + url = http://127.0.0.1/dummy/{z}/{x}/{y}.png, + attribution = {Dummy~tile~server}, + attribution~print = {Dummy~tile~server}, + basename = tiles/dummy, + } + +\__mermap_new_supply_source:nn { opentopomap } + { + url = https://tile.opentopomap.org/{z}/{x}/{y}.png, + attribution = { + Kartendaten:~\textcopyright\nobreakspace\href{https://openstreetmap.org/copyright}{OpenStreetMap} + \ Mitwirkende,~SRTM\nobreakspace\textbar\nobreakspace + Kartendarstellung:~\textcopyright\nobreakspace\href{http://opentopomap.org/}{OpenTopoMap} + \ (\href{https://creativecommons.org/licenses/by-sa/3.0/}{CC-BY-SA}) + }, + attribution~print = { + Kartendaten:~\textcopyright\nobreakspace www.openstreetmap.org/copyright, + \ SRTM\nobreakspace\textbar\nobreakspace + Kartendarstellung:~\textcopyright\nobreakspace opentopomap.org~(CC-BY-SA) + }, + basename = tiles/opentopomap, + } + +\keys_define:nn { mermap/supply } + { + __attribution_topplusopen .meta:nn = {mermap/supply} { + attribution = { + \textcopyright\nobreakspace\href{http://www.bkg.bund.de}{Bundesamt~f\mrcumlaut{u}r~Kartographie~und~Geod\mrcumlaut{a}sie}\nobreakspace\the\year, + \ \href{http://sg.geodatenzentrum.de/web_public/Datenquellen_TopPlus_Open.pdf}{Datenquellen} + }, + attribution~print = { + \textcopyright\nobreakspace Bundesamt~f\mrcumlaut{u}r~Kartographie~und~Geod\mrcumlaut{a}sie\nobreakspace\the\year, + \ Datenquellen:~\detokenize{http://sg.geodatenzentrum.de/web_public/Datenquellen_TopPlus_Open.pdf} + } + } + } + +\__mermap_new_supply_source:nn { topplusopen~web } + { + url = {https://sgx.geodatenzentrum.de/wmts_topplus_open/tile/1.0.0/web/default/WEBMERCATOR/{z}/{y}/{x}.png}, + __attribution_topplusopen, + basename = tiles/tpo_web, + } + +\__mermap_new_supply_source:nn { topplusopen~web~grau } + { + url = {https://sgx.geodatenzentrum.de/wmts_topplus_open/tile/1.0.0/web_grau/default/WEBMERCATOR/{z}/{y}/{x}.png}, + __attribution_topplusopen, + basename = tiles/tpo_web_grau, + } + +\cs_new:Npn \__mermap_new_supply_source_topplusopen:n #1 + { + \keys_define:nn { mermap/supply/_source } + { + topplusopen~#1 .meta:nn = {mermap/supply}{ + url = {https://sgx.geodatenzentrum.de/wms_topplus_open?service=wms&version=1.3.0&request=GetMap&Layers=#1&STYLES=default&CRS=EPSG:3857&bbox={xmin},{ymin},{xmax},{ymax}&width={width}&height={height}&Format=image/png}, + __attribution_topplusopen, + basename = tiles/tpo, + }, + topplusopen~#1~grau .meta:nn = {mermap/supply}{ + url = {https://sgx.geodatenzentrum.de/wms_topplus_open?service=wms&version=1.3.0&request=GetMap&Layers=#1_grau&STYLES=default&CRS=EPSG:3857&bbox={xmin},{ymin},{xmax},{ymax}&width={width}&height={height}&Format=image/png}, + __attribution_topplusopen, + basename = tiles/tpo, + }, + } + } +\__mermap_new_supply_source_topplusopen:n { p5 } +\__mermap_new_supply_source_topplusopen:n { p10 } +\__mermap_new_supply_source_topplusopen:n { p17.5 } +\__mermap_new_supply_source_topplusopen:n { p25 } +\__mermap_new_supply_source_topplusopen:n { p50 } +\__mermap_new_supply_source_topplusopen:n { p100 } +\__mermap_new_supply_source_topplusopen:n { p250 } + +\__mermap_new_supply_source:nn { openrouteservice~mapsurfer } + { + url~with~api~key = {https://api.openrouteservice.org/mapsurfer/{z}/{x}/{y}.png?api_key=}{openrouteservice}{}, + attribution = { + Service~\textcopyright\nobreakspace\href{https://openrouteservice.org/}{openrouteservice.org} + \nobreakspace\textbar\nobreakspace + Map~data~\textcopyright\nobreakspace\href{https://openstreetmap.org/copyright}{OpenStreetMap}~contributors + }, + attribution~print = { + Service~\textcopyright\nobreakspace openrouteservice.org + \nobreakspace\textbar\nobreakspace + Map~data~\textcopyright\nobreakspace OpenStreetMap~contributors + }, + basename = tiles/mapsurfer, + } + +\keys_define:nn { mermap/supply } + { + __attribution_stamen .meta:nn = {mermap/supply} { + attribution = { + Map~tiles~by~\href{http://stamen.com}{Stamen~Design}, + \ under~\href{http://creativecommons.org/licenses/by/3.0}{CC~BY~3.0}. + \ Data~by~\href{http://openstreetmap.org}{OpenStreetMap}, + \ under~\href{http://www.openstreetmap.org/copyright}{ODbL}. + }, + attribution~print = { + Map~tiles~by~Stamen~Design~(stamen.com), + \ under~CC~BY~3.0. + \ Data~by~OpenStreetMap, + \ under~ODbl~(www.openstreetmap.org/copyright). + } + } + } +\__mermap_new_supply_source:nn { stamen~terrain } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/terrain/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/terrain, + } +\__mermap_new_supply_source:nn { stamen~terrain-background } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/terrain-background/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/terrain-background, + } +\__mermap_new_supply_source:nn { stamen~terrain-labels } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/terrain-labels/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/terrain-labels, + } +\__mermap_new_supply_source:nn { stamen~terrain-lines } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/terrain-lines/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/terrain-lines, + } +\__mermap_new_supply_source:nn { stamen~toner } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/toner/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/toner, + } +\__mermap_new_supply_source:nn { stamen~toner-lite } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/toner-lite, + } +\__mermap_new_supply_source:nn { stamen~toner-hybrid } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/toner-hybrid/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/toner-hybrid, + } +\__mermap_new_supply_source:nn { stamen~toner-background } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/toner-background/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/toner-background, + } +\__mermap_new_supply_source:nn { stamen~toner-labels } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/toner-labels/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/toner-labels, + } +\__mermap_new_supply_source:nn { stamen~toner-lines } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/toner-lines/{z}/{x}/{y}.png}, + __attribution_stamen, + basename = tiles/toner-lines, + } +\__mermap_new_supply_source:nn { stamen~watercolor } + { + url = {https://stamen-tiles-a.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.png}, + attribution = { + Map~tiles~by~\href{http://stamen.com}{Stamen~Design}, + \ under~\href{http://creativecommons.org/licenses/by/3.0}{CC~BY~3.0}. + \ Data~by~\href{http://openstreetmap.org}{OpenStreetMap}, + \ under~\href{http://creativecommons.org/licenses/by-sa/3.0}{CC~BY~SA}. + }, + attribution~print = { + Map~tiles~by~Stamen~Design~(stamen.com), + \ under~CC~BY~3.0. + \ Data~by~OpenStreetMap, + \ under~CC~BY~SA. + }, + basename = tiles/watercolor, + } + +\keys_define:nn { mermap/supply } + { + __attribution_thunderforest .meta:nn = {mermap/supply} { + attribution = { + Maps~\textcopyright\nobreakspace\href{https://www.thunderforest.com/}{Thunderforest}, + \ Data~\textcopyright\nobreakspace\href{https://openstreetmap.org/copyright}{OpenStreetMap~contributors} + }, + attribution~print = { + Maps~\textcopyright\nobreakspace www.thunderforest.com, + \ Data~\textcopyright\nobreakspace www.osm.org/copyright + } + } + } +\__mermap_new_supply_source:nn { thunderforest~opencyclemap } + { + url~with~api~key = {https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=}{thunderforest}{}, + __attribution_thunderforest, + basename = tiles/opencyclemap, + } +\__mermap_new_supply_source:nn { thunderforest~transport } + { + url~with~api~key = {https://tile.thunderforest.com/transport/{z}/{x}/{y}.png?apikey=}{thunderforest}{}, + __attribution_thunderforest, + basename = tiles/transport, + } +\__mermap_new_supply_source:nn { thunderforest~landscape } + { + url~with~api~key = {https://tile.thunderforest.com/landscape/{z}/{x}/{y}.png?apikey=}{thunderforest}{}, + __attribution_thunderforest, + basename = tiles/landscape, + } +\__mermap_new_supply_source:nn { thunderforest~outdoors } + { + url~with~api~key = {https://tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=}{thunderforest}{}, + __attribution_thunderforest, + basename = tiles/outdoors, + } +\__mermap_new_supply_source:nn { thunderforest~transport-dark } + { + url~with~api~key = {https://tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png?apikey=}{thunderforest}{}, + __attribution_thunderforest, + basename = tiles/transport-dark, + } +\__mermap_new_supply_source:nn { thunderforest~spinal-map } + { + url~with~api~key = {https://tile.thunderforest.com/spinal-map/{z}/{x}/{y}.png?apikey=}{thunderforest}{}, + __attribution_thunderforest, + basename = tiles/spinal-map, + } +\__mermap_new_supply_source:nn { thunderforest~pioneer } + { + url~with~api~key = {https://tile.thunderforest.com/pioneer/{z}/{x}/{y}.png?apikey=}{thunderforest}{}, + __attribution_thunderforest, + basename = tiles/pioneer, + } +\__mermap_new_supply_source:nn { thunderforest~mobile-atlas } + { + url~with~api~key = {https://tile.thunderforest.com/mobile-atlas/{z}/{x}/{y}.png?apikey=}{thunderforest}{}, + __attribution_thunderforest, + basename = tiles/mobile-atlas, + } +\__mermap_new_supply_source:nn { thunderforest~neighbourhood } + { + url~with~api~key = {https://tile.thunderforest.com/neighbourhood/{z}/{x}/{y}.png?apikey=}{thunderforest}{}, + __attribution_thunderforest, + basename = tiles/neighbourhood, + } + -- cgit v1.2.3