% -------------------------------------------------------------------------- % the ENdiagram package % % easy creation of potential energy curve diagrams % % -------------------------------------------------------------------------- % Clemens Niederberger % Web: https://www.bitbucket.org/cgnieder/endiagram % E-Mail: contact@mychemistry.eu % -------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % -------------------------------------------------------------------------- % Copyright 2012--2013 Clemens Niederberger % % 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 `maintained'. % % The Current Maintainer of this work is Clemens Niederberger. % % This work consists of the files endiagram.sty, endiagram_en.tex, % README and the derived file endiagram_en.pdf. % -------------------------------------------------------------------------- \RequirePackage{ expl3 , xparse , l3keys2e , tikz , siunitx } \usetikzlibrary{calc} \ProvidesExplPackage {endiagram} {2014/06/28} {0.1d} {Easy creation of potential energy curve diagrams} % -------------------------------------------------------------------------- % check expl3 version: \@ifpackagelater { expl3 } { 2013/12/14 } { } { \PackageError { endiagram } { Support~package~expl3~too~old } { You~need~to~update~your~installation~of~the~bundles~'l3kernel'~and~ 'l3packages'.\MessageBreak Loading~endiagram~will~abort! } \tex_endinput:D } % --------------------------------------------------------------------------- % % error and warning messages \msg_new:nnnn { ENdiagram } { points-missing } { You~need~at~least~three~values~for~drawing~the~energy~curve~ \msg_line_context: } { You~need~at~least~three~values~for~drawing~the~energy~curve~ \msg_line_context: } \msg_new:nnnn { ENdiagram } { ShowEa } { Wrong~argument~syntax.~ \msg_line_context: } { Wrong~argument~syntax.~ \msg_line_context: } \msg_new:nnnn { ENdiagram } { MakeOrigin } { You~can't~use~\token_to_str:N \ENcurve \c_space_tl after~ \token_to_str:N \MakeOrigin \c_space_tl \msg_line_context: } { You~can't~use~\token_to_str:N \ENcurve \c_space_tl after~ \token_to_str:N \MakeOrigin \c_space_tl \msg_line_context: } \msg_new:nnnn { ENdiagram } { outside-ENdiagram } { The~command~\token_to_str:N #1 \c_space_tl can~only~be~used~inside~the~ `endiagram'~environment. } { It~seems~you~have~used~\token_to_str:N #1 \c_space_tl outside~the~ `endiagram'~environment~where~it~isn't~allowed~(and~not~at~all~useful,~ anyway).~ However,~it~can~only~be~used~inside~the~`endiagram'~environment. } % --------------------------------------------------------------------------- % % tikz helper functions \cs_new:Npn \endiagram_node:n #1 { \node [ #1 ] } \cs_generate_variant:Nn \endiagram_node:n { o,f,x } \cs_new:Npn \endiagram_draw:n #1 { \draw [ #1 ] } \cs_generate_variant:Nn \endiagram_draw:n { o,f,x } \cs_new:Npn \endiagram_draw:nn #1#2 { \draw [ #1 ] #2 ; } \cs_generate_variant:Nn \endiagram_draw:nn { no,nf,nx,oo,of,ox,fn,fo,ff,fx,xn,xo,xf,xx } \cs_new:Npn \endiagram_tikz:n #1 { \tikz [ #1 ] } \cs_generate_variant:Nn \endiagram_tikz:n { o,f,x } \cs_new:Npn \endiagram_tikz:nn #1#2 { \tikz [ #1 ] { #2 } } \cs_generate_variant:Nn \endiagram_tikz:nn { no,nf,nx,oo,of,ox,fn,fo,ff,fx,xn,xo,xf,xx } \cs_new:Npn \endiagram_start_tikzpicture:n #1 { \tikzpicture [ #1 ] } \cs_generate_variant:Nn \endiagram_start_tikzpicture:n { o,f,x } \cs_new_eq:NN \endiagram_end_tikzpicture: \endtikzpicture % --------------------------------------------------------------------------- % % temporary variables: \tl_new:N \l__Endiagram_tmpa_tl \tl_new:N \l__Endiagram_tmpb_tl \tl_new:N \l__Endiagram_tmpc_tl \fp_new:N \l__Endiagram_tmpa_fp \fp_new:N \l__Endiagram_tmpb_fp \fp_new:N \l__Endiagram_tmpc_fp \fp_new:N \g__Endiagram_tmpa_fp \dim_new:N \l__endiagram_tmpa_dim \dim_new:N \g__Endiagram_tmpa_dim % --------------------------------------------------------------------------- % % restrict commands to use inside the endiagram environment: \bool_new:N \l__Endiagram_inside_env_bool \cs_new_protected:Npn \Endiagram_new_environment_command:Nnn #1#2#3 { \NewDocumentCommand #1 { #2 } { \bool_if:NTF \l__Endiagram_inside_env_bool { #3 } { \msg_warning:nnn { ENdiagram } { outside-ENdiagram } { #1 } } } } % --------------------------------------------------------------------------- % % draw the curve \clist_new:N \l__endiagram_points_clist \prop_new:N \l__endiagram_points_prop \int_new:N \l__endiagram_points_int \int_zero:N \l__endiagram_points_int \int_new:N \g__endiagram_curve_int \int_gzero:N \g__endiagram_curve_int \int_new:N \g__endiagram_points_max_int \int_new:N \l__endiagram_points_counter_int \int_set:Nn \l__endiagram_points_counter_int { 1 } \tl_new:N \l__endiagram_draw_curve_tl \tl_new:N \l__endiagram_curve_tikz_tl \tl_new:N \l__endiagram_curve_looseness_tl \tl_set:Nn \l__endiagram_curve_looseness_tl { .5 } \tl_new:N \l__endiagram_points_step_tl \tl_set:Nn \l__endiagram_points_step_tl { 2 } \tl_new:N \l__endiagram_points_step_default_tl \tl_set_eq:NN \l__endiagram_points_step_default_tl \l__endiagram_points_step_tl \fp_new:N \g__endiagram_y_min_fp \fp_gzero:N \g__endiagram_y_min_fp \fp_new:N \g__endiagram_y_max_fp \fp_gzero:N \g__endiagram_y_max_fp \fp_new:N \g__endiagram_x_min_fp \fp_gzero:N \g__endiagram_x_min_fp \fp_new:N \g__endiagram_x_max_fp \fp_gzero:N \g__endiagram_x_max_fp \bool_new:N \l__endiagram_debug_bool \bool_new:N \l__endiagram_curve_minima_bool \keys_define:nn { ENdiagram / ENcurve } { step .tl_set:N = \l__endiagram_points_step_tl , looseness .tl_set:N = \l__endiagram_curve_looseness_tl , tikz .tl_set:N = \l__endiagram_curve_tikz_tl , minima .bool_set:N = \l__endiagram_curve_minima_bool } \cs_new_protected:Npn \__endiagram_determine_yaxis_length:n #1 { \fp_compare:nNnT { #1 } < { \g__endiagram_y_min_fp } { \fp_gset:Nn \g__endiagram_y_min_fp { #1 } } \fp_compare:nNnT { #1 } > { \g__endiagram_y_max_fp } { \fp_gset:Nn \g__endiagram_y_max_fp { #1 } } } \cs_new_protected:Npn \__endiagram_determine_xaxis_length: { % TODO: adapt to (not so) new l3fp: \fp_gset:Nn \g__endiagram_x_max_fp { \int_to_arabic:n { \g__endiagram_points_max_int } } \fp_gsub:Nn \g__endiagram_x_max_fp { 1 } \exp_args:NNo \fp_gset:Nn \g__endiagram_x_max_fp { \g__endiagram_x_max_fp * \l__endiagram_points_step_tl } } \Endiagram_new_environment_command:Nnn \ENcurve { o m } { \bool_if:NT \l__endiagram_origin_made_bool { \msg_error:nn { ENdiagram } { MakeOrigin } } \int_gincr:N \g__endiagram_curve_int \tl_set_eq:NN \l__endiagram_points_step_tl \l__endiagram_points_step_default_tl \IfNoValueF { #1 } { \keys_set:nn { ENdiagram / ENcurve } { #1 } } \clist_clear:N \l__endiagram_points_clist \tl_clear:N \l__endiagram_draw_curve_tl \int_set:Nn \l__endiagram_points_counter_int { 1 } \clist_map_inline:nn { #2 } { \fp_set:Nn \l__Endiagram_tmpa_fp { ( \int_to_arabic:n { \l__endiagram_points_int } ) * \l__endiagram_points_step_tl } \tl_if_in:nnTF { ##1 } { [ } { \__endiagram_save_points:fxnn { \int_use:N \l__endiagram_points_int } { \fp_to_tl:N \l__Endiagram_tmpa_fp } ##1 } { \__endiagram_save_points:fxnn { \int_use:N \l__endiagram_points_int } { \fp_to_tl:N \l__Endiagram_tmpa_fp } { ##1 } [ 0 ] } } \int_zero:N \l__endiagram_points_int \int_gset:Nn \g__endiagram_points_max_int { \clist_count:N \l__endiagram_points_clist } \int_compare:nT { \g__endiagram_points_max_int < 3 } { \msg_error:nn { ENdiagram } { points-missing } } \clist_map_inline:Nn \l__endiagram_points_clist { \int_compare:nT { \l__endiagram_points_counter_int = 1 } { \fp_gset:Nn \g__endiagram_y_min_fp { ##1 } \bool_if:NT \l__endiagram_curve_minima_bool { \tl_put_right:Nn \l__endiagram_draw_curve_tl { ($(-.5,##1)+(0,.2)$) to [bend~right] } } } \__endiagram_determine_yaxis_length:n { ##1 } \__endiagram_determine_xaxis_length: \fp_set:Nn \l__Endiagram_tmpa_fp { \int_to_arabic:n { \l__endiagram_points_counter_int } -1 } \prop_get:NxN \l__endiagram_points_prop { \fp_to_tl:N \l__Endiagram_tmpa_fp } \l__Endiagram_tmpb_tl \tl_put_right:Nx \l__endiagram_draw_curve_tl { ($ { \l__Endiagram_tmpb_tl } *(1,0)+(0,##1) $) node[inner~sep=0] ( N \int_to_arabic:n { \g__endiagram_curve_int } - \int_to_arabic:n { \l__endiagram_points_counter_int } ) {} } \bool_if:NT \l__endiagram_debug_bool { \tl_put_right:Nx \l__endiagram_draw_curve_tl { node[anchor=north~west,font={\exp_not:N \tiny},inner~sep=0,color=black,fill=yellow!20] { N \int_to_arabic:n { \g__endiagram_curve_int } - \int_to_arabic:n { \l__endiagram_points_counter_int } } node[inner~sep=0,above,color=red,font={\exp_not:N \tiny}] {(\l__Endiagram_tmpb_tl,##1)} } } \int_compare:nT { \l__endiagram_points_counter_int < \g__endiagram_points_max_int } { \tl_put_right:Nn \l__endiagram_draw_curve_tl { to } } \int_compare:nT { \l__endiagram_points_counter_int = \g__endiagram_points_max_int } { \bool_if:NT \l__endiagram_curve_minima_bool { \tl_put_right:Nx \l__endiagram_draw_curve_tl { to [bend~right] ($ { \l__endiagram_points_step_tl * (\int_to_arabic:n { \l__endiagram_points_counter_int } - 1 ) } *(1,0)+(0,##1)+(.5,.2) $) } } } \int_incr:N \l__endiagram_points_counter_int } \endiagram_draw:xo { \l__endiagram_curve_tikz_tl, out=0,in=180, looseness=\l__endiagram_curve_looseness_tl } { \l__endiagram_draw_curve_tl } \tl_clear:N \l__endiagram_curve_tikz_tl } \cs_generate_variant:Nn \tl_put_right:Nn { Nx } \cs_new_protected:Npn \__endiagram_save_points:nnnn #1#2#3[#4] { \fp_set:Nn \l__Endiagram_tmpa_fp { #2 + #4 } \clist_put_right:Nn \l__endiagram_points_clist { #3 } \prop_put:Nox \l__endiagram_points_prop { #1 } { \fp_to_tl:N \l__Endiagram_tmpa_fp } \int_incr:N \l__endiagram_points_int } \cs_generate_variant:Nn \__endiagram_save_points:nnnn { fx } \cs_generate_variant:Nn \prop_put:Nnn { Nox } % --------------------------------------------------------------------------- % % show the energy levels \int_new:N \l__endiagram_niveau_counter_int \int_set:Nn \l__endiagram_niveau_counter_int { 1 } \tl_new:N \l__endiagram_niveau_tikz_tl \tl_new:N \l__endiagram_niveau_length_tl \tl_set:Nn \l__endiagram_niveau_length_tl { 1 } \tl_new:N \l__endiagram_niveau_shift_tl \tl_set:Nn \l__endiagram_niveau_shift_tl { 0 } \bool_new:N \l__endiagram_niveau_pick_bool \clist_new:N \l__endiagram_niveau_clist \keys_define:nn { ENdiagram / ShowNiveaus } { tikz .tl_set:N = \l__endiagram_niveau_tikz_tl , length .tl_set:N = \l__endiagram_niveau_length_tl , shift .tl_set:N = \l__endiagram_niveau_shift_tl , niveau .code:n = { \bool_set_true:N \l__endiagram_niveau_pick_bool \clist_clear:N \l__endiagram_niveau_clist \clist_set:Nn \l__endiagram_niveau_clist { #1 } } } \Endiagram_new_environment_command:Nnn \ShowNiveaus { o } { \group_begin: \IfNoValueF { #1 } { \keys_set:nn { ENdiagram / ShowNiveaus } { #1 } } \bool_if:NTF \l__endiagram_niveau_pick_bool { \clist_map_inline:Nn \l__endiagram_niveau_clist { \endiagram_draw:xn { \exp_not:V \l__endiagram_niveau_tikz_tl } { (##1) ++ (\l__endiagram_niveau_shift_tl,0) ++(-.5*\l__endiagram_niveau_length_tl,0) -- ++(\l__endiagram_niveau_length_tl,0) } } } { \int_do_until:nn { \l__endiagram_niveau_counter_int > \g__endiagram_points_max_int } { \endiagram_draw:xn { \exp_not:V \l__endiagram_niveau_tikz_tl } { ( N \int_to_arabic:n { \g__endiagram_curve_int } - \int_to_arabic:n { \l__endiagram_niveau_counter_int } ) ++ (\l__endiagram_niveau_shift_tl,0) ++(-.5*\l__endiagram_niveau_length_tl,0) -- ++(\l__endiagram_niveau_length_tl,0) } \int_incr:N \l__endiagram_niveau_counter_int } } \group_end: } % --------------------------------------------------------------------------- % % show the energy gain \bool_new:N \l__endiagram_show_gain_right_bool \bool_new:N \l__endiagram_gain_label_bool \bool_new:N \l__endiagram_gain_own_label_bool \bool_new:N \l__endiagram_gain_connect_from_niveau_bool \tl_new:N \l__endiagram_gain_label_text_tl \tl_new:N \l__endiagram_gain_label_side_tl \tl_set:Nn \l__endiagram_gain_label_side_tl { right } \tl_new:N \l__endiagram_gain_label_pos_tl \tl_set:Nn \l__endiagram_gain_label_pos_tl { .5 } \tl_new:N \l__endiagram_gain_label_tikz_tl \tl_new:N \l__endiagram_gain_tikz_tl \tl_set:Nn \l__endiagram_gain_tikz_tl { <-> } \tl_new:N \l__endiagram_gain_connect_tikz_tl \tl_set:Nn \l__endiagram_gain_connect_tikz_tl { dashed,help~lines } \tl_new:N \l__endiagram_gain_x_value_tl \tl_new:N \l__endiagram_gain_offset_tl \tl_set:Nn \l__endiagram_gain_offset_tl { 0 } \tl_new:N \g__endiagram_gain_offset_tl \tl_gset:Nn \g__endiagram_gain_offset_tl { 0 } \tl_new:N \l__endiagram_gain_value_tl \keys_define:nn { ENdiagram / ShowGain } { tikz .tl_set:N = \l__endiagram_gain_tikz_tl , connect .tl_set:N = \l__endiagram_gain_connect_tikz_tl , connect-from-line .bool_set:N = \l__endiagram_gain_connect_from_niveau_bool , connect-from-line .default:n = true , offset .tl_set:N = \l__endiagram_gain_offset_tl , label .code:n = { \tl_if_eq:nnTF { true } { #1 } { \bool_set_true:N \l__endiagram_gain_label_bool } { \tl_if_eq:nnF { false } { #1 } { \bool_set_true:N \l__endiagram_gain_label_bool \bool_set_true:N \l__endiagram_gain_own_label_bool \tl_set:Nn \l__endiagram_gain_label_text_tl { #1 } } } } , label .default:n = true , label-side .choice: , label-side / right .code:n = { \tl_set:Nn \l__endiagram_gain_label_side_tl { right } } , label-side / left .code:n = { \tl_set:Nn \l__endiagram_gain_label_side_tl { left } } , label-pos .tl_set:N = \l__endiagram_gain_label_pos_tl , label-tikz .tl_set:N = \l__endiagram_gain_label_tikz_tl } \Endiagram_new_environment_command:Nnn \ShowGain { o } { \bool_set_true:N \l__endiagram_show_gain_right_bool \group_begin: \IfNoValueF { #1 } { \keys_set:nn { ENdiagram / ShowGain } { #1 } } \fp_compare:nNnT { \g__endiagram_gain_offset_tl } < { \l__endiagram_gain_offset_tl } { \tl_gset_eq:NN \g__endiagram_gain_offset_tl \l__endiagram_gain_offset_tl } \tl_set:Nx \l__endiagram_gain_x_value_tl { \int_to_arabic:n { \int_eval:n { \g__endiagram_points_max_int - 1} } } \endiagram_draw:xn { \exp_not:V \l__endiagram_gain_tikz_tl } { let \p1 = (N\int_to_arabic:n { \g__endiagram_curve_int }-1) , \p2 = (N\int_to_arabic:n { \g__endiagram_curve_int }-\int_to_arabic:n { \g__endiagram_points_max_int }) in ($\l__endiagram_points_step_tl*(\l__endiagram_gain_x_value_tl,0)+(\l__endiagram_gain_offset_tl+1,\y1)$) -- ($\l__endiagram_points_step_tl*(\l__endiagram_gain_x_value_tl,0)+(\l__endiagram_gain_offset_tl+1,\y2)$) node[pos=0,inner~sep=0] (gain-start\int_to_arabic:n { \g__endiagram_curve_int }) {} node[pos=1,inner~sep=0] (gain-end\int_to_arabic:n { \g__endiagram_curve_int }) {} } \fp_set:Nn \l__Endiagram_tmpa_fp { \clist_item:Nn \l__endiagram_points_clist { 1 } } \fp_set:Nn \l__Endiagram_tmpb_fp { \clist_item:Nn \l__endiagram_points_clist { \g__endiagram_points_max_int } } % \fp_sub:Nn \l__Endiagram_tmpb_tl { 1 } \fp_set:Nn \l__Endiagram_tmpc_fp { \l__endiagram_gain_x_value_tl * \l__endiagram_points_step_tl + \l__endiagram_gain_offset_tl + 1 } \bool_if:NT \l__endiagram_debug_bool { \endiagram_draw:nn {font=\tiny,inner~sep=0} { let \p1 = ( gain-start\int_to_arabic:n { \g__endiagram_curve_int } ) , \p2 = ( gain-end\int_to_arabic:n { \g__endiagram_curve_int } ) in node[right=2pt,fill=yellow!10] at ( \p1 ) { gain-start\int_to_arabic:n { \g__endiagram_curve_int } } node[right=2pt,fill=yellow!10] at ( \p2 ) { gain-end\int_to_arabic:n { \g__endiagram_curve_int } } node[above~right,red] at (\p1) {(\fp_to_tl:N \l__Endiagram_tmpc_fp,\fp_to_tl:N \l__Endiagram_tmpa_fp)} node[above~right,red] at (\p2) {(\fp_to_tl:N \l__Endiagram_tmpc_fp,\fp_to_tl:N \l__Endiagram_tmpb_fp)} } } \bool_if:NT \l__endiagram_gain_label_bool { \bool_if:NF \l__endiagram_gain_own_label_bool { \bool_if:nTF { \l__endiagram_energy_unit_bool && \l__endiagram_calculate_bool } { \fp_set:Nn \l__Endiagram_tmpb_fp { (\l__Endiagram_tmpb_fp - \l__Endiagram_tmpa_fp) * \l__endiagram_energy_step_tl } \fp_set:Nn \l__Endiagram_tmpb_fp { round( \l__Endiagram_tmpb_fp , \l__endiagram_energy_round_tl ) } \tl_set:Nx \l__endiagram_gain_value_tl { = \exp_not:N \SI { \fp_to_tl:N \l__Endiagram_tmpb_fp } { \exp_not:V \l__endiagram_energy_unit_tl } } % \tl_show:N \l__endiagram_gain_value_tl } { \fp_compare:nNnTF { \l__Endiagram_tmpa_fp } > { \l__Endiagram_tmpb_fp } { \tl_set:Nn \l__endiagram_gain_value_tl { < 0 } } { \tl_set:Nn \l__endiagram_gain_value_tl { > 0 } } } \tl_set:Nn \l__endiagram_gain_label_text_tl { $\Delta H \l__endiagram_gain_value_tl$ } } \endiagram_draw:nx {} { ($ (gain-end\int_to_arabic:n { \g__endiagram_curve_int }) !\l__endiagram_gain_label_pos_tl! (gain-start\int_to_arabic:n { \g__endiagram_curve_int })$) node [ \l__endiagram_gain_label_side_tl , \exp_not:V \l__endiagram_gain_label_tikz_tl ] { \exp_not:V \l__endiagram_gain_label_text_tl } } } \bool_if:NTF \l__endiagram_gain_connect_from_niveau_bool { \endiagram_draw:xf { \exp_not:V \l__endiagram_gain_connect_tikz_tl } { let \p1 = (N\int_to_arabic:n { \g__endiagram_curve_int }-1) , \p2 = (N\int_to_arabic:n { \g__endiagram_curve_int }-\int_to_arabic:n { \g__endiagram_points_max_int }) in (gain-end\int_to_arabic:n { \g__endiagram_curve_int }) ++ (.5,0) -- ($(\p2)+(.5*\l__endiagram_niveau_length_tl,0)$) (gain-start\int_to_arabic:n { \g__endiagram_curve_int }) ++ (.5,0) -- ($(\p1)+(.5*\l__endiagram_niveau_length_tl,0)$) } } { \endiagram_draw:xf { \exp_not:V \l__endiagram_gain_connect_tikz_tl } { let \p1 = (N\int_to_arabic:n { \g__endiagram_curve_int }-1) , \p2 = (N\int_to_arabic:n { \g__endiagram_curve_int }-\int_to_arabic:n { \g__endiagram_points_max_int }) in (gain-end\int_to_arabic:n { \g__endiagram_curve_int }) ++ (.5,0) -- (\p2) (gain-start\int_to_arabic:n { \g__endiagram_curve_int }) ++ (.5,0) -- (\p1) } } \group_end: } % --------------------------------------------------------------------------- % % show the activation energy \bool_new:N \l__endiagram_ea_all_bool \bool_new:N \l__endiagram_ea_coordinates_bool \bool_new:N \l__endiagram_ea_coordinates_points_bool \bool_new:N \l__endiagram_ea_label_bool \bool_new:N \l__endiagram_ea_own_label_bool \int_new:N \g__endiagram_ea_int \int_gzero:N \g__endiagram_ea_int \int_new:N \l__endiagram_ea_count_int \int_zero:N \l__endiagram_ea_count_int \tl_new:N \l__endiagram_ea_tikz_tl \tl_set:Nn \l__endiagram_ea_tikz_tl { <-> } \tl_new:N \l__endiagram_ea_connect_tikz_tl \tl_set:Nn \l__endiagram_ea_connect_tikz_tl { dashed, help~lines } \tl_new:N \l__endiagram_ea_label_text_tl \tl_set_rescan:Nnn \l__endiagram_ea_label_text_tl { \char_set_catcode_math_subscript:N \_ } { $E_{\mathrm{a}}$ } \tl_new:N \l__endiagram_ea_value_tl \tl_new:N \l__endiagram_ea_label_tikz_tl \tl_new:N \l__endiagram_ea_label_side_tl \tl_set:Nn \l__endiagram_ea_label_side_tl { right } \tl_new:N \l__endiagram_ea_label_pos_tl \tl_set:Nn \l__endiagram_ea_label_pos_tl { .5} \tl_new:N \l__endiagram_ea_start_node_tl \tl_new:N \l__endiagram_ea_end_node_tl \fp_new:N \l__endiagram_ea_connect_start_fp \fp_new:N \l__endiagram_ea_connect_end_fp \keys_define:nn { ENdiagram / ShowEa } { max .choice: , max / all .code:n = \bool_set_true:N \l__endiagram_ea_all_bool , max / first .code:n = \bool_set_false:N \l__endiagram_ea_all_bool , tikz .tl_set:N = \l__endiagram_ea_tikz_tl , connect .tl_set:N = \l__endiagram_ea_connect_tikz_tl , from .code:n = { \bool_set_true:N \l__endiagram_ea_coordinates_bool \__endiagram_detect_ea:n { #1 } } , label .code:n = { \tl_if_eq:nnTF { true } { #1 } { \bool_set_true:N \l__endiagram_ea_label_bool } { \tl_if_eq:nnF { false } { #1 } { \bool_set_true:N \l__endiagram_ea_own_label_bool \bool_set_true:N \l__endiagram_ea_label_bool \tl_set:Nn \l__endiagram_ea_label_text_tl { #1 } } } } , label .default:n = true , label-side .choice: , label-side / right .code:n = { \tl_set:Nn \l__endiagram_ea_label_side_tl { right } } , label-side / left .code:n = { \tl_set:Nn \l__endiagram_ea_label_side_tl { left } } , label-pos .tl_set:N = \l__endiagram_ea_label_pos_tl , label-tikz .tl_set:N = \l__endiagram_ea_label_tikz_tl } \cs_new_protected:Npn \__endiagram_detect_ea:n #1 { % remember blanks \tl_set:Nn \l__Endiagram_tmpa_tl { #1 } \tl_replace_all:Nnn \l__Endiagram_tmpa_tl { ~ } { @@@ } \exp_after:wN \__endiagram_detect_ea_auxi:nn \l__Endiagram_tmpa_tl \q_nil } \cs_new_protected:Npn \__endiagram_detect_ea_auxi:nn (#1) #2 \q_nil { % recover blanks in node #1 \tl_set:Nn \l__Endiagram_tmpa_tl { #1 } \tl_replace_all:Nnn \l__Endiagram_tmpa_tl { @@@ } { ~ } \tl_set_eq:NN \l__endiagram_ea_start_node_tl \l__Endiagram_tmpa_tl \__endiagram_detect_ea_auxii:nn #2 } \cs_new_protected:Npn \__endiagram_detect_ea_auxii:nn #1 (#2) { % recover blanks in node #2 \tl_set:Nn \l__Endiagram_tmpa_tl { #2 } \tl_set:Nn \l__Endiagram_tmpb_tl { #1 } \tl_replace_all:Nnn \l__Endiagram_tmpa_tl { @@@ } { ~ } \tl_set_eq:NN \l__endiagram_ea_end_node_tl \l__Endiagram_tmpa_tl % ignore blanks in between and test for right syntax \tl_remove_all:Nn \l__Endiagram_tmpb_tl { @@@ } \tl_if_eq:VnF \l__Endiagram_tmpb_tl { to } { \msg_error:nn { ENdiagram } { ShowEa } } } \cs_generate_variant:Nn \tl_if_eq:nnF { V } \Endiagram_new_environment_command:Nnn \ShowEa { o } { \int_gincr:N \g__endiagram_ea_int \group_begin: \IfNoValueF { #1 } { \keys_set:nn { ENdiagram / ShowEa } { #1 } } \bool_if:NTF \l__endiagram_ea_coordinates_bool { \endiagram_draw:xn { \exp_not:V \l__endiagram_ea_tikz_tl } { ( \l__endiagram_ea_end_node_tl |- \l__endiagram_ea_start_node_tl ) -- ( \l__endiagram_ea_end_node_tl ) } \bool_if:NT \l__endiagram_ea_label_bool { \bool_if:nT { \l__endiagram_energy_unit_bool && \l__endiagram_calculate_bool && !\l__endiagram_ea_own_label_bool } { % determine length of Ea-line \endiagram_draw:nn { } { let \p1 = (\l__endiagram_ea_start_node_tl), \p2 = (\l__endiagram_ea_end_node_tl) in node at (\p2) { \dim_gset:Nn \g__Endiagram_tmpa_dim { \y2 - \y1 } } } % convert length of Ea-line into energy value \fp_set:Nn \l__Endiagram_tmpb_fp { \dim_to_fp:Nn { 1cm } } \fp_set:Nn \l__Endiagram_tmpa_fp { \dim_to_fp:n { \g__Endiagram_tmpa_dim } / \l__Endiagram_tmpb_fp * \l__endiagram_energy_step_tl } \fp_set:Nn \l__Endiagram_tmpb_fp { round( \l__Endiagram_tmpb_fp , \l__endiagram_energy_round_tl ) } \tl_set:Nx \l__endiagram_ea_value_tl { ~ = ~ \exp_not:N \SI { \fp_to_tl:N \l__Endiagram_tmpa_fp } { \exp_not:V \l__endiagram_energy_unit_tl } } } \endiagram_draw:xn { \exp_not:V \l__endiagram_ea_label_tikz_tl } { node[\l__endiagram_ea_label_side_tl] at ($ (\l__endiagram_ea_end_node_tl) !\l__endiagram_ea_label_pos_tl! (\l__endiagram_ea_end_node_tl |- \l__endiagram_ea_start_node_tl) $) { \l__endiagram_ea_label_text_tl \l__endiagram_ea_value_tl } } } \endiagram_draw:xn { \exp_not:V \l__endiagram_ea_connect_tikz_tl } { ( \l__endiagram_ea_start_node_tl ) -- ( \l__endiagram_ea_end_node_tl |- \l__endiagram_ea_start_node_tl ) node ( ea-end \int_to_arabic:n { \g__endiagram_curve_int }- \int_to_arabic:n { \g__endiagram_ea_int }- 0 ) {} } \bool_if:NT \l__endiagram_debug_bool { \endiagram_draw:nn { inner~sep=0,font=\tiny } { ( ea-end \int_to_arabic:n { \g__endiagram_curve_int }- \int_to_arabic:n { \g__endiagram_ea_int }- 0 ) node[below~right,fill=yellow!10] { ea-end \int_to_arabic:n { \g__endiagram_curve_int }- \int_to_arabic:n { \g__endiagram_ea_int }- 0 } } } } { \int_do_until:nn { \l__endiagram_ea_count_int >= \g__endiagram_points_max_int - 1 } { \fp_set:Nn \l__Endiagram_tmpa_fp { \clist_item:Nn \l__endiagram_points_clist { \int_eval:n { \l__endiagram_ea_count_int + 1 } } } \fp_set:Nn \l__Endiagram_tmpb_fp { \clist_item:Nn \l__endiagram_points_clist { \int_eval:n { \l__endiagram_ea_count_int + 2 } } } \fp_compare:nNnT { \l__Endiagram_tmpa_fp } < { \l__Endiagram_tmpb_fp } { \prop_get:NfN \l__endiagram_points_prop { \int_eval:n { \l__endiagram_ea_count_int + 1 } } \l__Endiagram_tmpc_tl \fp_set:Nn \l__endiagram_ea_connect_end_fp { \l__Endiagram_tmpc_tl } \prop_get:NfN \l__endiagram_points_prop { \int_eval:n { \l__endiagram_ea_count_int } } \l__Endiagram_tmpc_tl \fp_set:Nn \l__endiagram_ea_connect_start_fp { \l__Endiagram_tmpc_tl } \endiagram_draw:xn { \exp_not:V \l__endiagram_ea_tikz_tl } { ( \fp_to_tl:N \l__endiagram_ea_connect_end_fp , \fp_to_tl:N \l__Endiagram_tmpa_fp ) node ( ea-end \int_to_arabic:n { \g__endiagram_curve_int }- \int_to_arabic:n { \g__endiagram_ea_int }- \int_to_arabic:n { \l__endiagram_ea_count_int } ) { } -- ( \fp_to_tl:N \l__endiagram_ea_connect_end_fp , \fp_to_tl:N \l__Endiagram_tmpb_fp ) } \bool_if:NT \l__endiagram_ea_label_bool { \bool_if:nT { \l__endiagram_energy_unit_bool && \l__endiagram_calculate_bool && !\l__endiagram_ea_own_label_bool } { \fp_set:Nn \l__Endiagram_tmpc_fp { ( \l__Endiagram_tmpb_fp - \l__Endiagram_tmpa_fp ) * \l__endiagram_energy_step_tl } \tl_gset:Nx \l__endiagram_ea_value_tl { ~ = ~ \exp_not:N \SI { \fp_to_tl:N \l__Endiagram_tmpc_fp } { \exp_not:V \l__endiagram_energy_unit_tl } } } \endiagram_draw:xn { \exp_not:V \l__endiagram_ea_label_tikz_tl } { node[\l__endiagram_ea_label_side_tl] at ($ ( \fp_to_tl:N \l__endiagram_ea_connect_end_fp , \fp_to_tl:N \l__Endiagram_tmpa_fp ) !\l__endiagram_ea_label_pos_tl! ( \fp_to_tl:N \l__endiagram_ea_connect_end_fp , \fp_to_tl:N \l__Endiagram_tmpb_fp ) $) { \l__endiagram_ea_label_text_tl \l__endiagram_ea_value_tl } } } \endiagram_draw:xn { \exp_not:V \l__endiagram_ea_connect_tikz_tl } { ( \fp_to_tl:N \l__endiagram_ea_connect_end_fp , \fp_to_tl:N \l__Endiagram_tmpa_fp ) -- ++ ( \fp_to_tl:N \l__endiagram_ea_connect_start_fp - \fp_to_tl:N \l__endiagram_ea_connect_end_fp , 0 ) } \bool_if:NT \l__endiagram_debug_bool { \endiagram_draw:nn { inner~sep=0,font=\tiny } { ( ea-end \int_to_arabic:n { \g__endiagram_curve_int }- \int_to_arabic:n { \g__endiagram_ea_int }- \int_to_arabic:n { \l__endiagram_ea_count_int } ) node[below~right,fill=yellow!10] { ea-end \int_to_arabic:n { \g__endiagram_curve_int }- \int_to_arabic:n { \g__endiagram_ea_int }- \int_to_arabic:n { \l__endiagram_ea_count_int } } node[above~right,red] { ( \fp_to_tl:N \l__endiagram_ea_connect_end_fp , \fp_to_tl:N \l__Endiagram_tmpa_fp ) } } } \bool_if:NF \l__endiagram_ea_all_bool { % set count unreasonably high to ensure we're over % \g__endiagram_points_max_int \int_add:Nn \l__endiagram_ea_count_int { 1000 } } } \int_incr:N \l__endiagram_ea_count_int } } \group_end: } \cs_generate_variant:Nn \prop_get:NnN { Nf , Nx } % --------------------------------------------------------------------------- % % add axis labels \bool_new:N \l__endiagram_add_axis_yl_bool \bool_set_true:N \l__endiagram_add_axis_yl_bool \bool_new:N \l__endiagram_add_axis_yr_bool \bool_new:N \l__endiagram_add_axis_x_bool \tl_new:N \l__endiagram_add_axis_connect_tl \tl_set:Nn \l__endiagram_add_axis_connect_tl { dashed,help~lines } \tl_new:N \l__endiagram_add_axis_font_tl \keys_define:nn { ENdiagram / AddAxisLabel } { axis .choice: , axis / y-l .code:n = { \bool_set_true:N \l__endiagram_add_axis_yl_bool \bool_set_false:N \l__endiagram_add_axis_yr_bool \bool_set_false:N \l__endiagram_add_axis_x_bool } , axis / y-r .code:n = { \bool_set_false:N \l__endiagram_add_axis_yl_bool \bool_set_true:N \l__endiagram_add_axis_yr_bool \bool_set_false:N \l__endiagram_add_axis_x_bool } , axis / x .code:n = { \bool_set_false:N \l__endiagram_add_axis_yl_bool \bool_set_false:N \l__endiagram_add_axis_yr_bool \bool_set_true:N \l__endiagram_add_axis_x_bool } , connect .tl_set:N = \l__endiagram_add_axis_connect_tl , font .tl_set:N = \l__endiagram_add_axis_font_tl } \Endiagram_new_environment_command:Nnn \AddAxisLabel { so > { \SplitList { ; } } m } { \MakeOrigin \group_begin: \tl_clear:N \l__Endiagram_tmpa_tl \tl_clear:N \l__Endiagram_tmpb_tl \tl_clear:N \l__Endiagram_tmpc_tl \IfNoValueF { #2 } { \keys_set:nn { ENdiagram / AddAxisLabel } { #2 } } \IfBooleanTF { #1 } { % list of "ticks" \bool_if:NT \l__endiagram_add_axis_yl_bool { \__endiagram_add_axis_label_yl_ticks:n { #3 } } \bool_if:NT \l__endiagram_add_axis_yr_bool { \__endiagram_add_axis_label_yr_ticks:n { #3 } } \bool_if:NT \l__endiagram_add_axis_x_bool { \__endiagram_add_axis_label_x_ticks:n { #3 } } } { % list of points \bool_if:NT \l__endiagram_add_axis_yl_bool { \__endiagram_add_axis_label_yl_points:n { #3 } } \bool_if:NT \l__endiagram_add_axis_yr_bool { \__endiagram_add_axis_label_yr_points:n { #3 } } \bool_if:NT \l__endiagram_add_axis_x_bool { \__endiagram_add_axis_label_x_points:n { #3 } } } \group_end: } \cs_new_protected:Npn \__endiagram_add_axis_label_yl_ticks:n #1 { \tl_map_inline:nn { #1 } { \tl_if_in:nnTF { ##1 } { [ } { \group_begin: \__endiagram_get_tick_arg_and_label:w ##1 \q_stop \fp_set:Nn \l__Endiagram_tmpb_fp { \l__Endiagram_label_tl } \bool_if:NT \l__endiagram_energy_bool { \fp_set:Nn \l__Endiagram_tmpb_fp { \l__Endiagram_tmpb_fp * \l__endiagram_energy_step_tl - \l__endiagram_energy_zero_tl } % \bool_if:NTF \l__endiagram_energy_round_places_bool % { \fp_set:Nn \l__Endiagram_tmpb_fp { round( \l__Endiagram_tmpb_fp , \l__endiagram_energy_round_tl ) } % \fp_round_places:Nn \l__Endiagram_tmpb_fp % { \l__endiagram_energy_round_tl } % } % { % \fp_round_figures:Nn \l__Endiagram_tmpb_fp % { \l__endiagram_energy_round_tl } % } \tl_set:Nn \l__Endiagram_tmpb_tl { \fp_to_tl:N \l__Endiagram_tmpb_fp } } \endiagram_draw:nx { } { let \exp_not:N \p1 = (origin-l) in ( \exp_not:N \x1 , \fp_to_tl:N \l__Endiagram_tmpa_fp ) -- ++ (-3pt,0) node [ left , font = \exp_not:V \l__endiagram_add_axis_font_tl , \exp_not:V \l__Endiagram_label_tikz_tl ] { \exp_not:V \l__Endiagram_label_tl } } \group_end: } { \fp_set:Nn \l__Endiagram_tmpa_fp { ##1 } \bool_if:NT \l__endiagram_energy_bool { \fp_set:Nn \l__Endiagram_tmpa_fp { \l__Endiagram_tmpa_fp * \l__endiagram_energy_step_tl - \l__endiagram_energy_zero_tl } } \endiagram_draw:nn { } { let \p1 = (origin-l) in ( \x1 , ##1 ) -- ++ (-3pt,0) node[left,font=\l__endiagram_add_axis_font_tl] { \fp_to_tl:N \l__Endiagram_tmpa_fp } } } } } % TODO: sollte Energie-Skala und Rundung beachten! \cs_new_protected:Npn \__endiagram_add_axis_label_yr_ticks:n #1 { \tl_map_inline:nn { #1 } { \tl_if_in:nnTF { ##1 } { [ } { \group_begin: \__endiagram_get_tick_arg_and_label:w ##1 \q_stop \endiagram_draw:nx { } { ( \fp_to_tl:N \g__endiagram_x_max_fp , \l__Endiagram_point_tl ) -- ++ (3pt,0) node [ right , font = \exp_not:V \l__endiagram_add_axis_font_tl , \exp_not:V \l__Endiagram_label_tikz_tl ] { \exp_not:V \l__Endiagram_label_tl } } \group_end: } { \endiagram_draw:nn { } { let \p1 = (origin-r) in ( \x1 , ##1 ) -- ++ (3pt,0) node[right,font=\l__endiagram_add_axis_font_tl] { ##1 } } } } } \cs_new_protected:Npn \__endiagram_add_axis_label_x_ticks:n #1 { \tl_map_inline:nn { #1 } { \tl_if_in:nnTF { ##1 } { [ } { \group_begin: \__endiagram_get_tick_arg_and_label:w ##1 \q_stop \endiagram_draw:nx { } { let \exp_not:N \p1 = (origin-l) in ( \l__Endiagram_point_tl , \exp_not:N \y1 ) -- ++ (-3pt,0) node [ below , font = \exp_not:V \l__endiagram_add_axis_font_tl , \exp_not:V \l__Endiagram_label_tikz_tl ] { \exp_not:V \l__Endiagram_label_tl } } \group_end: } { \endiagram_draw:nn { } { let \p1 = (origin-l) in ( ##1 , \y1 ) -- ++ (-3pt,0) node[below,font=\l__endiagram_add_axis_font_tl] { ##1 } } } } } \cs_new_protected:Npn \__endiagram_add_axis_label_yl_points:n #1 { \tl_map_inline:nn { #1 } { \tl_if_in:nnTF { ##1 } { [ } { \group_begin: \__endiagram_get_tick_point_and_label:w ##1 \q_stop \endiagram_draw:xn { \exp_not:V \l__endiagram_add_axis_connect_tl } { (\l__Endiagram_point_tl) -- (\l__Endiagram_point_tl -| origin-l) } \endiagram_draw:nx { } { (\l__Endiagram_point_tl -| origin-l) -- ++ (-3pt,0) node [ left , font = \exp_not:V \l__endiagram_add_axis_font_tl , \exp_not:V \l__Endiagram_label_tikz_tl ] { \exp_not:V \l__Endiagram_label_tl } } \group_end: } { \group_begin: \__endiagram_get_tick_node:w ##1 \q_stop \endiagram_draw:xn { \exp_not:V \l__endiagram_add_axis_connect_tl } { (\l__Endiagram_tick_node_tl) -- (\l__Endiagram_tick_node_tl -| origin-l) } \endiagram_draw:nn { } { (\l__Endiagram_tick_node_tl -| origin-l) -- ++ (-3pt,0) } \group_end: } } } \cs_new_protected:Npn \__endiagram_add_axis_label_yr_points:n #1 { \tl_map_inline:nn { #1 } { \tl_if_in:nnTF { ##1 } { [ } { \group_begin: \__endiagram_get_tick_point_and_label:w ##1 \q_stop \endiagram_draw:xn { \exp_not:V \l__endiagram_add_axis_connect_tl } { (\l__Endiagram_point_tl) -- (\l__Endiagram_point_tl -| origin-r) } \endiagram_draw:nx { } { (\l__Endiagram_point_tl -| origin-r) -- ++ (3pt,0) node [ right , font = \exp_not:V \l__endiagram_add_axis_font_tl , \exp_not:V \l__Endiagram_label_tikz_tl ] { \exp_not:V \l__Endiagram_label_tl } } \group_end: } { \group_begin: \__endiagram_get_tick_node:w ##1 \q_stop \endiagram_draw:xn { \exp_not:V \l__endiagram_add_axis_connect_tl } { (\l__Endiagram_tick_node_tl) -- (\l__Endiagram_tick_node_tl -| origin-r) } \endiagram_draw:nn { } { (\l__Endiagram_tick_node_tl -| origin-r) -- ++ (3pt,0) } \group_end: } } } \cs_new_protected:Npn \__endiagram_add_axis_label_x_points:n #1 { \tl_map_inline:nn { #1 } { \tl_if_in:nnTF { ##1 } { [ } { \group_begin: \__endiagram_get_tick_point_and_label:w ##1 \q_stop \endiagram_draw:xn { \exp_not:V \l__endiagram_add_axis_connect_tl } { (\l__Endiagram_point_tl) -- (\l__Endiagram_point_tl |- origin-l) } \endiagram_draw:nx { } { (\l__Endiagram_point_tl |- origin-l) -- ++ (-3pt,0) node [ below , font = \exp_not:V \l__endiagram_add_axis_font_tl , \exp_not:V \l__Endiagram_label_tikz_tl ] { \exp_not:V \l__Endiagram_label_tl } } \group_end: } { \group_begin: \__endiagram_get_tick_node:w ##1 \q_stop \endiagram_draw:xn { \exp_not:V \l__endiagram_add_axis_connect_tl } { (\l__Endiagram_tick_node_tl) -- (\l__Endiagram_tick_node_tl |- origin-l) } \endiagram_draw:nn { } { (\l__Endiagram_tick_node_tl |- origin-l) -- ++ (-3pt,0) } \group_end: } } } \cs_new_protected:Npn \__endiagram_get_tick_arg_and_label:w #1[#2] \q_stop { \fp_set:Nn \l__Endiagram_tmpa_fp { #1 } \endiagram_get_label_and_tikz:n { #2 } } \tl_new:N \l__Endiagram_point_tl \tl_new:N \l__Endiagram_tick_node_tl \tl_new:N \l__Endiagram_label_tl \tl_new:N \l__Endiagram_label_tikz_tl \cs_new_protected:Npn \__endiagram_get_tick_point_and_label:w (#1)[#2] \q_stop { \tl_set:Nn \l__Endiagram_point_tl { #1 } \endiagram_get_label_and_tikz:n { #2 } } \cs_new_protected:Npn \__endiagram_get_tick_node:w (#1) \q_stop { \tl_set:Nn \l__Endiagram_tick_node_tl { #1 } } \cs_new_protected:Npn \endiagram_get_label_and_tikz:n #1 { \tl_if_in:nnTF { #1 } { , } { \__endiagram_get_label_and_tikz_aux:w #1 \q_stop } { \tl_set:Nn \l__Endiagram_label_tl { #1 } } } \cs_new_protected:Npn \__endiagram_get_label_and_tikz_aux:w #1,#2 \q_stop { \tl_set:Nn \l__Endiagram_label_tl { #1 } \tl_set:Nn \l__Endiagram_label_tikz_tl { #2 } } % --------------------------------------------------------------------------- % % make origin \bool_new:N \l__endiagram_origin_made_bool \Endiagram_new_environment_command:Nnn \MakeOrigin {} { \bool_if:NF \l__endiagram_origin_made_bool { \bool_set_true:N \l__endiagram_origin_made_bool \fp_gsub:Nn \g__endiagram_y_min_fp { 1 } \fp_gadd:Nn \g__endiagram_y_max_fp { 1 } \fp_gsub:Nn \g__endiagram_x_min_fp { 1.5 } \fp_gsub:Nn \g__endiagram_x_min_fp { \l__endiagram_diagram_l_offset_tl } \fp_gadd:Nn \g__endiagram_x_max_fp { 1.5 } \endiagram_draw:nn {} { coordinate (origin-l) at (-1.5-\l__endiagram_diagram_l_offset_tl,\fp_to_tl:N \g__endiagram_y_min_fp ) } \bool_if:NT \l__endiagram_debug_bool { \fp_set:Nn \l__Endiagram_tmpa_tl { -1.5 } \fp_sub:Nn \l__Endiagram_tmpa_tl { \l__endiagram_diagram_l_offset_tl } \endiagram_draw:nn { red } { (origin-l) circle (2pt) } \endiagram_draw:nn { font=\tiny,inner~sep=0 } { node[above~right,red] at (origin-l) { ( \fp_to_tl:N \l__Endiagram_tmpa_tl , \fp_to_tl:N \g__endiagram_y_min_fp ) } node[fill=yellow!10,below~right] at (origin-l) { origin-l } } } \endiagram_draw:nn {} { coordinate (origin-r) at (\fp_to_tl:N \g__endiagram_x_max_fp ,\fp_to_tl:N \g__endiagram_y_min_fp ) } \bool_if:NT \l__endiagram_debug_bool { \endiagram_draw:nn { red } { (origin-r) circle (2pt) } \endiagram_draw:nn { font=\tiny,inner~sep=0 } { node[above~right,red] at (origin-r) { ( \fp_to_tl:N \g__endiagram_x_max_fp ,\fp_to_tl:N \g__endiagram_y_min_fp ) } node[fill=yellow!10,below~right] at (origin-r) { origin-r } } } } } % --------------------------------------------------------------------------- % % main environment \bool_new:N \l__endiagram_y_axis_left_bool \bool_set_true:N \l__endiagram_y_axis_left_bool \bool_new:N \l__endiagram_y_axis_right_bool \bool_new:N \l__endiagram_y_label_pos_bool \bool_set_true:N \l__endiagram_y_label_pos_bool \bool_new:N \l__endiagram_x_axis_bool \bool_set_true:N \l__endiagram_x_axis_bool \bool_new:N \l__endiagram_x_label_pos_bool \bool_set_true:N \l__endiagram_x_label_pos_bool \bool_new:N \l__endiagram_axes_all_bool \bool_new:N \l__endiagram_axes_ticks_bool \bool_new:N \l__endiagram_axes_ticks_yl_bool \bool_new:N \l__endiagram_axes_ticks_yr_bool \bool_new:N \l__endiagram_axes_add_ticks_bool \bool_new:N \l__endiagram_energy_bool \bool_new:N \l__endiagram_energy_unit_bool % \bool_new:N \l__endiagram_energy_round_places_bool \bool_new:N \l__endiagram_calculate_bool \bool_set_true:N \l__endiagram_calculate_bool \tl_new:N \l__endiagram_tikz_tl \tl_new:N \l__endiagram_y_axis_tikz_tl \tl_new:N \l__endiagram_x_axis_tikz_tl \tl_new:N \l__endiagram_axes_ticks_step_tl \tl_set:Nn \l__endiagram_axes_ticks_step_tl { 1 } \tl_new:N \l__endiagram_y_label_pos_tl \tl_set:Nn \l__endiagram_y_label_pos_tl { pos = .5 , } \tl_new:N \l__endiagram_y_label_anchor_tl \tl_set:Nn \l__endiagram_y_label_anchor_tl { sloped } \tl_new:N \l__endiagram_y_label_text_tl \tl_set:Nn \l__endiagram_y_label_text_tl { $E$ } \tl_new:N \l__endiagram_y_label_angle_tl \tl_set:Nn \l__endiagram_y_label_angle_tl { 0 } \tl_new:N \l__endiagram_y_label_offset_tl \tl_new:N \l__endiagram_x_label_pos_tl \tl_set:Nn \l__endiagram_x_label_pos_tl { pos = .5 , } \tl_new:N \l__endiagram_x_label_anchor_tl \tl_set:Nn \l__endiagram_x_label_anchor_tl { below } \tl_new:N \l__endiagram_x_label_text_tl \tl_set:Nn \l__endiagram_x_label_text_tl { $\xi$ } \tl_new:N \l__endiagram_x_label_angle_tl \tl_set:Nn \l__endiagram_x_label_angle_tl { 0 } \tl_new:N \l__endiagram_x_label_offset_tl \tl_new:N \l__endiagram_diagram_l_offset_tl \tl_set:Nn \l__endiagram_diagram_l_offset_tl { 0 } \tl_new:N \l__endiagram_diagram_r_offset_tl \tl_set:Nn \l__endiagram_diagram_r_offset_tl { 0 } \tl_new:N \l__endiagram_diagram_scale_tl \tl_set:Nn \l__endiagram_diagram_scale_tl { 1 } \tl_new:N \l__endiagram_diagram_unit_factor_tl \tl_set:Nn \l__endiagram_diagram_unit_factor_tl { .5 } \tl_new:N \l__endiagram_energy_step_tl \tl_set:Nn \l__endiagram_energy_step_tl { 1 } \tl_new:N \l__endiagram_energy_unit_tl \tl_new:N \l__endiagram_energy_unit_separator_tl \tl_set:Nn \l__endiagram_energy_unit_separator_tl { / } \tl_new:N \l__endiagram_energy_zero_tl \tl_set:Nn \l__endiagram_energy_zero_tl { 0 } \tl_new:N \l__endiagram_energy_round_tl \tl_set:Nn \l__endiagram_energy_round_tl { 3 } \cs_new_protected:Npn \__endiagram_determine_unit:n #1 { \dim_set:Nn \l__endiagram_tmpa_dim { 1pt * \dim_ratio:nn { #1 } { 1cm } } \tl_set:Nn \l__endiagram_diagram_unit_factor_tl { \dim_use:N \l__endiagram_tmpa_dim } \tl_remove_once:Nn \l__endiagram_diagram_unit_factor_tl { pt } } \keys_define:nn { ENdiagram } { debug .bool_set:N = \l__endiagram_debug_bool , debug .default:n = true , draft .bool_set:N = \l__endiagram_debug_bool , draft .default:n = true , final .choice: , final / true .code:n = { \bool_set_false:N \l__endiagram_debug_bool } , final / false .code:n = { \bool_set_true:N \l__endiagram_debug_bool } , final .default:n = true , axes .choice: , axes / y .code:n = { \bool_set_true:N \l__endiagram_y_axis_left_bool \bool_set_false:N \l__endiagram_y_axis_right_bool \bool_set_false:N \l__endiagram_x_axis_bool } , axes / y-l .code:n = { \bool_set_true:N \l__endiagram_y_axis_left_bool \bool_set_false:N \l__endiagram_y_axis_right_bool \bool_set_false:N \l__endiagram_x_axis_bool } , axes / y-r .code:n = { \bool_set_false:N \l__endiagram_y_axis_left_bool \bool_set_true:N \l__endiagram_y_axis_right_bool \bool_set_false:N \l__endiagram_x_axis_bool } , axes / x .code:n = { \bool_set_false:N \l__endiagram_y_axis_left_bool \bool_set_false:N \l__endiagram_y_axis_right_bool \bool_set_true:N \l__endiagram_x_axis_bool } , axes / xy .code:n = { \bool_set_true:N \l__endiagram_y_axis_left_bool \bool_set_false:N \l__endiagram_y_axis_right_bool \bool_set_true:N \l__endiagram_x_axis_bool } , axes / all .code:n = { \bool_set_true:N \l__endiagram_axes_all_bool } , axes / false .code:n = { \bool_set_false:N \l__endiagram_y_axis_left_bool \bool_set_false:N \l__endiagram_y_axis_right_bool \bool_set_false:N \l__endiagram_x_axis_bool } , y-axis .tl_set:N = \l__endiagram_y_axis_tikz_tl , x-axis .tl_set:N = \l__endiagram_x_axis_tikz_tl , y-label .choice: , y-label / above .code:n = { \bool_set_false:N \l__endiagram_y_label_pos_bool \tl_clear:N \l__endiagram_y_label_anchor_tl } , y-label / left .code:n = { \bool_set_true:N \l__endiagram_y_label_pos_bool \tl_set:Nn \l__endiagram_y_label_anchor_tl { sloped } } , % y-label-axis .code:n = , % TODO: left/right/both % darauf achten, dass das mit "axes" korreliert. y-label-pos .code:n = { \tl_set:Nn \l__endiagram_y_label_pos_tl { pos = #1 , } } , y-label-offset .code:n = { \tl_set:Nn \l__endiagram_y_label_offset_tl { = #1 } } , y-label-text .tl_set:N = \l__endiagram_y_label_text_tl , y-label-angle .tl_set:N = \l__endiagram_y_label_angle_tl , x-label .choice: , x-label / right .code:n = { \bool_set_false:N \l__endiagram_x_label_pos_bool \tl_set:Nn \l__endiagram_x_label_anchor_tl { right } } , x-label / below .code:n = { \bool_set_true:N \l__endiagram_x_label_pos_bool \tl_set:Nn \l__endiagram_x_label_anchor_tl { below } } , x-label-pos .code:n = { \tl_set:Nn \l__endiagram_x_label_pos_tl { pos = #1 , } } , x-label-offset .code:n = { \tl_set:Nn \l__endiagram_x_label_offset_tl { = #1 } } , x-label-text .tl_set:N = \l__endiagram_x_label_text_tl , x-label-angle .tl_set:N = \l__endiagram_x_label_angle_tl , offset .code:n = { \tl_set:Nn \l__endiagram_diagram_l_offset_tl { #1 } \tl_set:Nn \l__endiagram_diagram_r_offset_tl { #1 } } , l-offset .tl_set:N = \l__endiagram_diagram_l_offset_tl , r-offset .tl_set:N = \l__endiagram_diagram_r_offset_tl , scale .tl_set:N = \l__endiagram_diagram_scale_tl , unit .code:n = \__endiagram_determine_unit:n { #1 } , tikz .tl_set:N = \l__endiagram_tikz_tl , energy-step .code:n = \tl_set:Nn \l__endiagram_energy_step_tl { #1 } \bool_set_true:N \l__endiagram_energy_bool , energy-zero .tl_set:N = \l__endiagram_energy_zero_tl , energy-unit .code:n = \tl_set:Nn \l__endiagram_energy_unit_tl { #1 } \bool_set_true:N \l__endiagram_energy_unit_bool , energy-unit-separator .tl_set:N = \l__endiagram_energy_unit_separator_tl , % energy-round-places .bool_set:N = \l__endiagram_energy_round_places_bool , % energy-round-places .default:n = true , energy-round .tl_set:N = \l__endiagram_energy_round_tl , calculate .bool_set:N = \l__endiagram_calculate_bool , calculate .default:n = true , % TODO darauf achten, dass das mit "axes" korreliert ticks .choice: , ticks / y .code:n = \bool_set_true:N \l__endiagram_axes_ticks_bool , ticks / y-l .code:n = \bool_set_true:N \l__endiagram_axes_ticks_yl_bool , ticks / y-r .code:n = \bool_set_true:N \l__endiagram_axes_ticks_yr_bool , ticks / none .code:n = \bool_set_false:N \l__endiagram_axes_ticks_bool \bool_set_false:N \l__endiagram_axes_ticks_yl_bool \bool_set_false:N \l__endiagram_axes_ticks_yr_bool , ticks .default:n = y , ticks-step .tl_set:N = \l__endiagram_axes_ticks_step_tl } \NewDocumentEnvironment { endiagram } { o } { \IfNoValueF { #1 } { \keys_set:nn { ENdiagram } { #1 } } \bool_set_true:N \l__Endiagram_inside_env_bool \int_gzero:N \g__endiagram_curve_int \endiagram_start_tikzpicture:x { scale=\l__endiagram_diagram_scale_tl*\l__endiagram_diagram_unit_factor_tl , \l__endiagram_tikz_tl } } { \MakeOrigin % linke y-Achse \bool_if:NT \l__endiagram_energy_unit_bool { \tl_put_right:Nx \l__endiagram_y_label_text_tl { \exp_not:V \l__endiagram_energy_unit_separator_tl \exp_not:N \si { \exp_not:V \l__endiagram_energy_unit_tl } } } \bool_if:nT { \l__endiagram_y_axis_left_bool || \l__endiagram_axes_all_bool } { \bool_if:NF \l__endiagram_y_label_pos_bool { \tl_clear:N \l__endiagram_y_label_pos_tl } \endiagram_draw:xx { -> , \exp_not:V \l__endiagram_y_axis_tikz_tl } { (-1.5-\l__endiagram_diagram_l_offset_tl,\fp_to_tl:N \g__endiagram_y_min_fp ) -- (-1.5-\l__endiagram_diagram_l_offset_tl,\fp_to_tl:N \g__endiagram_y_max_fp ) node [ \l__endiagram_y_label_pos_tl above \l__endiagram_y_label_offset_tl , rotate = \l__endiagram_y_label_angle_tl , \l__endiagram_y_label_anchor_tl ] { \exp_not:V \l__endiagram_y_label_text_tl } } % TODO: "energy-zero" beachten: ticks auch am Nullpunkt starten, egal ob dort auch ein niveau sitzt \bool_if:nT { \l__endiagram_axes_ticks_bool || \l__endiagram_axes_ticks_yl_bool } { \bool_set_true:N \l__endiagram_axes_add_ticks_bool \fp_set:Nn \l__Endiagram_tmpa_fp { \g__endiagram_y_min_fp + \l__endiagram_axes_ticks_step_tl } \bool_while_do:Nn \l__endiagram_axes_add_ticks_bool { \fp_set_eq:NN \l__Endiagram_tmpb_fp \l__Endiagram_tmpa_fp \tl_clear:N \l__Endiagram_tmpc_tl \__endiagram_add_axis_label_yl_ticks:n { { \l__Endiagram_tmpa_fp [ \fp_to_tl:N \l__Endiagram_tmpb_fp ] } } \fp_add:Nn \l__Endiagram_tmpa_fp { \l__endiagram_axes_ticks_step_tl } \fp_compare:nNnF { \l__Endiagram_tmpa_fp } < { \g__endiagram_y_max_fp } { \bool_set_false:N \l__endiagram_axes_add_ticks_bool } } } } % x-Achse \bool_if:NT \l__endiagram_show_gain_right_bool { \fp_gadd:Nn \g__endiagram_x_max_fp { \g__endiagram_gain_offset_tl } \fp_gadd:Nn \g__endiagram_x_max_fp { 1 } } \fp_gadd:Nn \g__endiagram_x_max_fp { \l__endiagram_diagram_r_offset_tl } \bool_if:nT { \l__endiagram_x_axis_bool || \l__endiagram_axes_all_bool } { \bool_if:NF \l__endiagram_x_label_pos_bool { \tl_clear:N \l__endiagram_x_label_pos_tl } \endiagram_draw:xx { \bool_if:nT { \l__endiagram_x_axis_bool && !\l__endiagram_y_axis_right_bool && !\l__endiagram_axes_all_bool } { -> , } \exp_not:V \l__endiagram_x_axis_tikz_tl } { (-1.5-\l__endiagram_diagram_l_offset_tl,\fp_to_tl:N \g__endiagram_y_min_fp ) -- (\fp_to_tl:N \g__endiagram_x_max_fp ,\fp_to_tl:N \g__endiagram_y_min_fp ) node [ \l__endiagram_x_label_pos_tl rotate = \l__endiagram_x_label_angle_tl , sloped , \l__endiagram_x_label_anchor_tl \l__endiagram_x_label_offset_tl , ] { \exp_not:V \l__endiagram_x_label_text_tl } } } % rechte y-Achse \bool_if:nT { \l__endiagram_y_axis_right_bool || \l__endiagram_axes_all_bool } { \endiagram_draw:xf { -> , \exp_not:V \l__endiagram_y_axis_tikz_tl } { (\fp_to_tl:N \g__endiagram_x_max_fp,\fp_to_tl:N \g__endiagram_y_min_fp) -- (\fp_to_tl:N \g__endiagram_x_max_fp,\fp_to_tl:N \g__endiagram_y_max_fp ) } % TODO "energy-zero" beachten! Ticks werden nicht gezeichnet, wenn nicht extra spezifiziert \bool_if:nT { \l__endiagram_axes_ticks_bool || \l__endiagram_axes_ticks_yr_bool } { \bool_set_true:N \l__endiagram_axes_add_ticks_bool \fp_set:Nn \l__Endiagram_tmpa_fp { \g__endiagram_y_min_fp + \l__endiagram_axes_ticks_step_tl } \bool_while_do:Nn \l__endiagram_axes_add_ticks_bool { \fp_set:Nn \l__Endiagram_tmpb_fp { \l__Endiagram_tmpa_fp * \l__endiagram_energy_step_tl } \tl_clear:N \l__Endiagram_tmpc_tl \__endiagram_add_axis_label_yr_ticks:n { { \l__Endiagram_tmpa_fp [ \fp_to_tl:N \l__Endiagram_tmpb_fp ] } } \fp_add:Nn \l__Endiagram_tmpa_fp { \l__endiagram_axes_ticks_step_tl } \fp_compare:nNnF { \l__Endiagram_tmpa_fp } < { \g__endiagram_y_max_fp } { \bool_set_false:N \l__endiagram_axes_add_ticks_bool } } } } \bool_if:NT \l__endiagram_debug_bool { \fp_add:Nn \g__endiagram_x_max_fp { 1 } \fp_add:Nn \g__endiagram_y_max_fp { 1 } \fp_sub:Nn \g__endiagram_x_min_fp { 1 } \fp_sub:Nn \g__endiagram_y_min_fp { 1 } \draw[help~lines,densely~dotted,opacity=.7] (\fp_to_tl:N \g__endiagram_x_min_fp,\fp_to_tl:N \g__endiagram_y_min_fp) grid (\fp_to_tl:N \g__endiagram_x_max_fp,\fp_to_tl:N \g__endiagram_y_max_fp) ; \draw[red] (0,0) circle (3pt) node[right,font=\tiny] at (0,0) {(0,0)} ; } \endiagram_end_tikzpicture: \fp_gzero:N \g__endiagram_y_min_fp \fp_gzero:N \g__endiagram_y_max_fp \fp_gzero:N \g__endiagram_x_max_fp \fp_gzero:N \g__endiagram_x_min_fp \tl_gset:Nn \g__endiagram_gain_offset_tl { 0 } \int_gzero:N \g__endiagram_ea_int } % --------------------------------------------------------------------------- % % setup \NewDocumentCommand \ENsetup { om } { \IfNoValueTF { #1 } { \keys_set:nn { ENdiagram } { #2 } } { \keys_set:nn { ENdiagram / #1 } { #2 } } } % --------------------------------------------------------------------------- % % package options: \ProcessKeysOptions { ENdiagram } \tex_endinput:D %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Version history 2012/02/31 v0.0 2012/06/26 v0.1 2012/08/20 v0.1a - most basic necessary changes due to new l3fp module => more revisions on various places still needed! 2013/04/04 v0.1b - changed deprecated \clist_length:N into \clist_count:N 2013/04/18 v0.1c - bug fix: the y- and x-labels should not be expanded, made internal commands protected where appropriate - various internal changes, most importantly care of not expanding user input that is not supposed to 2014/06/28 v0.1d - adapt to deprecated expl3 function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % TODO - the whole code should be cleaned up... an embarrising mess! - \ENcurve und \AddAxisLabel so anpassen, dass Eingaben der Energieskala folgen?! - revise the whole code especially with respect to fp calculations