%% wheelchart.sty %% Copyright 2023 Matthias Floré % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % 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.3c 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 Matthias Floré. % % This work consists of the files wheelchart.pdf, wheelchart.sty, % wheelchart.tex and README.md. \NeedsTeXFormat{LaTeX2e} \RequirePackage{tikz} \usetikzlibrary{calc} \ProvidesExplPackage{wheelchart}{2023/12/03}{2.0}{Draw wheelcharts with TikZ} %%> \subsection{Variables} \newcounter { g__wheelchart_WCcount_counter } \bool_new:N \l__wheelchart_arc_bool \bool_new:N \l__wheelchart_contour_bool \bool_new:N \g__wheelchart_def_angle_radius_shift_bool \bool_new:N \l__wheelchart_def_inner_contour_bool \bool_new:N \l__wheelchart_discrete_bool \bool_new:N \l__wheelchart_etoc_use_name_bool \bool_new:N \l__wheelchart_legend_only_bool \bool_new:N \l__wheelchart_legend_row_bool \bool_new:N \l__wheelchart_lines_ext_dir_bool \bool_new:N \l__wheelchart_middle_fill_bool \bool_new:N \l__wheelchart_pie_bool \bool_new:N \l__wheelchart_plot_bool \bool_new:N \l__wheelchart_slices_bool \bool_new:N \l__wheelchart_wheel_lines_bool \box_new:N \l__wheelchart_arc_data_box \box_new:N \g__wheelchart_if_text_box \clist_new:N \l__wheelchart_header_clist \clist_new:N \g__wheelchart_slice_range_for_loop_clist \clist_new:N \l__wheelchart_slice_range_local_clist \fp_const:Nn \c__wheelchart_arc_data_end_factor_center_fp { 0.5 } \fp_const:Nn \c__wheelchart_arc_data_end_factor_left_fp { 1 } \fp_const:Nn \c__wheelchart_arc_data_end_factor_right_fp { 0 } \fp_const:Nn \c__wheelchart_arc_data_start_factor_center_fp { -0.5 } \fp_const:Nn \c__wheelchart_arc_data_start_factor_left_fp { 0 } \fp_const:Nn \c__wheelchart_arc_data_start_factor_right_fp { -1 } \fp_new:N \l__wheelchart_abs_half_angle_minus_new_angle_fp \fp_new:N \l__wheelchart_abs_half_angle_minus_new_angle_minus_gap_polar_fp \fp_new:N \l__wheelchart_anchor_xsep_fp \fp_new:N \l__wheelchart_anchor_ysep_fp \fp_new:N \g__wheelchart_angle_fp \fp_new:N \l__wheelchart_angle_wheel_lines_fp \fp_new:N \l__wheelchart_arc_data_angle_pos_fp \fp_new:N \l__wheelchart_arc_data_angle_shift_fp \fp_new:N \l__wheelchart_arc_data_dir_fp \fp_new:N \g__wheelchart_arc_data_factor_fp \fp_new:N \l__wheelchart_arc_data_pos_fp \fp_new:N \l__wheelchart_arc_data_sep_fp \fp_new:N \g__wheelchart_arc_data_slice_length_fp \fp_new:N \l__wheelchart_arc_pos_fp \fp_new:N \l__wheelchart_arc_sep_fp \fp_new:N \l__wheelchart_coord_determinant_fp \fp_new:N \l__wheelchart_counter_or_clockwise_fp \fp_new:N \l__wheelchart_data_angle_pos_fp \fp_new:N \l__wheelchart_data_angle_shift_fp \fp_new:N \l__wheelchart_data_pos_fp \fp_new:N \l__wheelchart_data_sep_fp \fp_new:N \g__wheelchart_def_angle_angle_fp \fp_new:N \l__wheelchart_discrete_end_length_fp \fp_new:N \l__wheelchart_discrete_factor_fp \fp_new:N \l__wheelchart_discrete_inner_length_fp \fp_new:N \l__wheelchart_discrete_level_fp \fp_new:N \l__wheelchart_discrete_level_end_length_fp \fp_new:N \l__wheelchart_discrete_level_start_length_fp \fp_new:N \l__wheelchart_discrete_levels_sum_fp \fp_new:N \l__wheelchart_discrete_outer_length_fp \fp_new:N \l__wheelchart_discrete_start_length_fp \fp_new:N \l__wheelchart_discrete_sublevel_end_length_fp \fp_new:N \l__wheelchart_discrete_sublevel_start_length_fp \fp_new:N \l__wheelchart_explode_fp \fp_new:N \l__wheelchart_gap_fp \fp_new:N \l__wheelchart_gap_max_angle_fp \fp_new:N \l__wheelchart_gap_max_angle_def_fp \fp_new:N \l__wheelchart_gap_polar_fp \fp_new:N \l__wheelchart_gap_radius_fp \fp_new:N \g__wheelchart_half_ex_over_one_cm_fp \fp_new:N \l__wheelchart_inner_data_angle_pos_fp \fp_new:N \l__wheelchart_inner_data_angle_shift_fp \fp_new:N \l__wheelchart_inner_data_pos_fp \fp_new:N \l__wheelchart_inner_data_sep_fp \fp_new:c { l__wheelchart_inner~end_x_fp } \fp_new:c { l__wheelchart_inner~end_y_fp } \fp_new:N \l__wheelchart_inner_gap_fp \fp_new:N \l__wheelchart_inner_plot_variable_fp \fp_new:N \l__wheelchart_inner_radius_fp \fp_new:N \l__wheelchart_inner_radius_orig_fp \fp_new:c { l__wheelchart_inner~start_x_fp } \fp_new:c { l__wheelchart_inner~start_y_fp } \fp_new:N \l__wheelchart_lines_fp \fp_new:N \l__wheelchart_lines_angle_pos_fp \fp_new:N \l__wheelchart_lines_angle_shift_fp \fp_new:N \l__wheelchart_lines_ext_fp \fp_new:N \l__wheelchart_lines_ext_dirsep_fp \fp_new:N \l__wheelchart_lines_ext_fixed_left_fp \fp_new:N \l__wheelchart_lines_ext_fixed_right_fp \fp_new:N \l__wheelchart_lines_pos_fp \fp_new:N \l__wheelchart_lines_sep_fp \fp_new:N \g__wheelchart_new_angle_fp \fp_new:c { l__wheelchart_outer~end_x_fp } \fp_new:c { l__wheelchart_outer~end_y_fp } \fp_new:N \l__wheelchart_outer_gap_fp \fp_new:N \l__wheelchart_outer_plot_variable_fp \fp_new:N \l__wheelchart_outer_radius_fp \fp_new:c { l__wheelchart_outer~start_x_fp } \fp_new:c { l__wheelchart_outer~start_y_fp } \fp_new:N \l__wheelchart_plot_variable_fp \fp_new:N \g__wheelchart_previous_x_coord_fp \fp_new:N \g__wheelchart_previous_y_coord_fp \fp_new:N \l__wheelchart_samples_fp \fp_new:N \l__wheelchart_slice_inner_end_angle_fp \fp_new:N \l__wheelchart_slice_inner_start_angle_fp \fp_new:N \l__wheelchart_slice_outer_end_angle_fp \fp_new:N \l__wheelchart_slice_outer_start_angle_fp \fp_new:N \l__wheelchart_slices_angle_fp \fp_new:N \l__wheelchart_slices_angle_pos_fp \fp_new:N \l__wheelchart_slices_angle_shift_fp \fp_new:N \l__wheelchart_slices_arc_A_fp \fp_new:N \l__wheelchart_slices_arc_A_abs_fp \fp_new:N \l__wheelchart_slices_arc_angle_fp \fp_new:N \l__wheelchart_slices_arc_B_fp \fp_new:N \l__wheelchart_slices_arc_coord_fp \fp_new:N \l__wheelchart_slices_arc_rotate_fp \fp_new:N \l__wheelchart_slices_arrow_A_fp \fp_new:N \l__wheelchart_slices_arrow_B_fp \fp_new:N \l__wheelchart_slices_arrow_coord_fp \fp_new:N \l__wheelchart_slices_inner_end_angle_shift_fp \fp_new:N \l__wheelchart_slices_inner_start_angle_shift_fp \fp_new:N \g__wheelchart_slices_orientation_fp \fp_new:N \l__wheelchart_slices_orientation_new_angle_fp \fp_new:N \l__wheelchart_slices_outer_end_angle_shift_fp \fp_new:N \l__wheelchart_slices_outer_start_angle_shift_fp \fp_new:N \l__wheelchart_slices_pos_fp \fp_new:N \l__wheelchart_slices_sep_fp \fp_new:N \l__wheelchart_start_angle_fp \fp_new:N \l__wheelchart_total_angle_fp \fp_new:N \l__wheelchart_total_count_fp \fp_new:N \l__wheelchart_value_fp \fp_new:N \g__wheelchart_value_global_fp \fp_new:N \l__wheelchart_wheel_data_angle_pos_fp \fp_new:N \l__wheelchart_wheel_data_angle_shift_fp \fp_new:N \l__wheelchart_wheel_data_pos_fp \fp_new:N \l__wheelchart_wheel_data_sep_fp \fp_new:N \g__wheelchart_x_coord_fp \fp_new:N \g__wheelchart_y_coord_fp \int_const:Nn \c__wheelchart_lines_ext_dir_left_int { -1 } \int_const:Nn \c__wheelchart_lines_ext_dir_right_int { 1 } \int_new:N \g__wheelchart_discrete_count_int \int_new:N \l__wheelchart_discrete_levels_int \int_new:N \l__wheelchart_discrete_partitioning_first_index_int \int_new:N \l__wheelchart_discrete_partitioning_second_index_int \int_new:N \l__wheelchart_discrete_sort_int \int_new:N \l__wheelchart_discrete_space_at_borders_int \int_set:Nn \l__wheelchart_discrete_space_at_borders_int { -1 } \int_new:N \l__wheelchart_discrete_sublevels_int \int_new:N \l__wheelchart_etoc_count_total_pages_int \int_new:N \l__wheelchart_legend_columns_int \int_new:N \l__wheelchart_legend_rows_int \int_new:N \l__wheelchart_lines_ext_bottom_dir_int \int_new:N \l__wheelchart_lines_ext_dir_int \int_new:N \l__wheelchart_lines_ext_top_dir_int \int_new:N \l__wheelchart_slice_range_index_int \seq_new:N \l__wheelchart_discrete_coefficients_first_seq \seq_new:N \l__wheelchart_discrete_coefficients_second_seq \seq_new:N \l__wheelchart_discrete_points_seq \seq_new:N \l__wheelchart_list_seq \seq_new:N \l__wheelchart_list_items_seq \tl_new:N \l__wheelchart_arc_data_align_tl \tl_new:N \l__wheelchart_data_anchor_tl \tl_new:N \l__wheelchart_etoc_level_tl \tl_new:N \l__wheelchart_etoc_name_tl \tl_new:N \l__wheelchart_expand_list_tl \tl_new:N \l__wheelchart_expand_list_items_tl \tl_new:N \g__wheelchart_inner_contour_tl \tl_new:N \l__wheelchart_key_name_tl \tl_new:N \l__wheelchart_key_range_tl \tl_new:N \l__wheelchart_legend_row_tl \tl_new:N \g__wheelchart_name_tl \tl_new:N \g__wheelchart_outer_contour_tl \tl_new:N \l__wheelchart_slices_tl \tl_new:N \l__wheelchart_slices_end_tl \tl_set:Nn \l__wheelchart_slices_end_tl { -- ( \fp_use:c { l__wheelchart_inner~end_x_fp } , \fp_use:c { l__wheelchart_inner~end_y_fp } ) } \tl_new:N \l__wheelchart_slices_inner_tl \tl_set:Nn \l__wheelchart_slices_inner_tl { \fp_compare:nNnT { \l__wheelchart_inner_radius_fp } > { 0 } { \fp_compare:nNnT { \l__wheelchart_inner_gap_fp } < { \l__wheelchart_abs_half_angle_minus_new_angle_fp } { arc [ start~angle = \fp_use:N \l__wheelchart_slice_inner_end_angle_fp , end~angle = \fp_use:N \l__wheelchart_slice_inner_start_angle_fp , radius = \fp_use:N \l__wheelchart_inner_radius_fp ] } } } \tl_new:N \l__wheelchart_slices_outer_tl \tl_set:Nn \l__wheelchart_slices_outer_tl { arc [ start~angle = \fp_use:N \l__wheelchart_slice_outer_start_angle_fp , end~angle = \fp_use:N \l__wheelchart_slice_outer_end_angle_fp , radius = \fp_use:N \l__wheelchart_outer_radius_fp ] } \tl_new:N \l__wheelchart_slices_start_tl \tl_set:Nn \l__wheelchart_slices_start_tl { -- cycle } \tl_new:N \l__wheelchart_type_tl \tl_set:Nn \l__wheelchart_type_tl { default } %%> \subsection{Functions} \cs_generate_variant:Nn \seq_set_split:Nnn { Nen , Neo } \cs_generate_variant:Nn \tl_build_put_right:Nn { NV } \cs_new:Npn \__wheelchart_arc_around_text:nnn #1#2#3 { \__wheelchart_convex_comb_coord_plot:nnnnnnn { draw , / wheelchart / arc_style , / wheelchart / arc_#1_half } { \fp_eval:n { \l__wheelchart_arc_data_angle_pos_fp + 0.5 * \g__wheelchart_arc_data_factor_fp * ( sign ( \l__wheelchart_arc_data_dir_fp ) * ( \fp_use:c { c__wheelchart_arc_data_start_factor_\l__wheelchart_arc_data_align_tl _fp } + \fp_use:c { c__wheelchart_arc_data_end_factor_\l__wheelchart_arc_data_align_tl _fp } ) + #2 ) } } {#3} { \l__wheelchart_plot_variable_fp } { 0 } { \l__wheelchart_arc_pos_fp } { \l__wheelchart_arc_sep_fp } } \cs_new:Npn \__wheelchart_caption_and_title:nnnnn #1#2#3#4#5 { \__wheelchart_if_text:nn {#1} { \node [ anchor = #2 , align = #3 , / wheelchart / #1_style ] at ( $ (#4) + ( 0 , { #5 * ( \pgfkeysvalueof { / wheelchart / #1~sep } ) } ) $ ) { \pgfkeysvalueof { / wheelchart / #1 } } ; } } \cs_new:Npn \__wheelchart_convex_comb_coord_aux:n #1 { (#1) } \cs_generate_variant:Nn \__wheelchart_convex_comb_coord_aux:n { o } \cs_new:Npn \__wheelchart_convex_comb_coord_def:nnnn #1#2#3#4 { $ ( \__wheelchart_inner_plot:nn { \fp_eval:n { ( 1 - (#1) ) * \l__wheelchart_slice_inner_start_angle_fp + (#1) * \l__wheelchart_slice_inner_end_angle_fp + \l__wheelchart_counter_or_clockwise_fp * (#2) } } { \fp_eval:n { \l__wheelchart_inner_radius_fp - (#4) } } ) ! { \fp_eval:n {#3} } ! ( \__wheelchart_outer_plot:nn { \fp_eval:n { ( 1 - (#1) ) * \l__wheelchart_slice_outer_start_angle_fp + (#1) * \l__wheelchart_slice_outer_end_angle_fp + \l__wheelchart_counter_or_clockwise_fp * (#2) } } { \fp_eval:n { \l__wheelchart_outer_radius_fp + (#4) } } ) $%note the () around the #i's to keep these contents together } \cs_new:Npn \__wheelchart_convex_comb_coord:nnnn #1#2#3#4 { \__wheelchart_convex_comb_coord_aux:o { \__wheelchart_convex_comb_coord_def:nnnn {#1} {#2} {#3} {#4} } } \cs_new:Npn \__wheelchart_convex_comb_coord_plot_aux:nnnn #1#2#3#4 { \path [#1] plot [ domain = {#2} \c_colon_str {#3} , samples = \fp_use:N \l__wheelchart_samples_fp , variable = \l__wheelchart_plot_variable_fp ] ( {#4} ) ; } \cs_generate_variant:Nn \__wheelchart_convex_comb_coord_plot_aux:nnnn { nnno } \cs_new:Npn \__wheelchart_convex_comb_coord_plot:nnnnnnn #1#2#3#4#5#6#7 { \__wheelchart_convex_comb_coord_plot_aux:nnno {#1} {#2} {#3} { \__wheelchart_convex_comb_coord_def:nnnn {#4} {#5} {#6} { \g__wheelchart_half_ex_over_one_cm_fp + (#7) } } } \cs_new:Npn \__wheelchart_def_angle:nnnN #1#2#3#4 { \path let \p { l__wheelchart_def_angle_1 } = \__wheelchart_convex_comb_coord:nnnn {#1} {#2} { 0 } {#3} , \p { l__wheelchart_def_angle_2 } = \__wheelchart_convex_comb_coord:nnnn {#1} {#2} { 1 } {#3} in [ / utils / exec = { \bool_gset:Nn \g__wheelchart_def_angle_radius_shift_bool { \fp_compare_p:n { \y { l__wheelchart_def_angle_2 } - \y { l__wheelchart_def_angle_1 } == 0 && \x { l__wheelchart_def_angle_2 } - \x { l__wheelchart_def_angle_1 } == 0 } } \bool_if:NF \g__wheelchart_def_angle_radius_shift_bool { \fp_gset:Nn \g__wheelchart_def_angle_angle_fp { atand ( \y { l__wheelchart_def_angle_2 } - \y { l__wheelchart_def_angle_1 } , \x { l__wheelchart_def_angle_2 } - \x { l__wheelchart_def_angle_1 } ) }%here \pgf@xx and so on are not used } } ] ; \bool_if:NT \g__wheelchart_def_angle_radius_shift_bool { \path let \p { l__wheelchart_def_angle_1 } = \__wheelchart_convex_comb_coord:nnnn {#1} {#2} { 0 } { \fp_eval:n { (#3) + 1 / \l__wheelchart_samples_fp } } , \p { l__wheelchart_def_angle_2 } = \__wheelchart_convex_comb_coord:nnnn {#1} {#2} { 1 } { \fp_eval:n { (#3) + 1 / \l__wheelchart_samples_fp } } in [ / utils / exec = { \fp_gset:Nn \g__wheelchart_def_angle_angle_fp { atand ( \y { l__wheelchart_def_angle_2 } - \y { l__wheelchart_def_angle_1 } , \x { l__wheelchart_def_angle_2 } - \x { l__wheelchart_def_angle_1 } ) } } ] ;%here \pgf@xx and so on are not used } \pgfmathsetmacro {#4} { Mod ( \fp_use:N \g__wheelchart_def_angle_angle_fp , 360 ) } } \cs_new:Npn \__wheelchart_def_coord_aux:nn #1#2 { \path let \p { l__wheelchart_coord } = ( \use:c { __wheelchart_#1_plot:nn } {#2} { \fp_use:c { l__wheelchart_#1_radius_fp } } ) in [ / utils / exec = { \fp_gset:Nn \g__wheelchart_x_coord_fp { ( \pgf@yy * \x { l__wheelchart_coord } - \pgf@yx * \y { l__wheelchart_coord } ) / \l__wheelchart_coord_determinant_fp } \fp_gset:Nn \g__wheelchart_y_coord_fp { ( \pgf@xx * \y { l__wheelchart_coord } - \pgf@xy * \x { l__wheelchart_coord } ) / \l__wheelchart_coord_determinant_fp } } ] ; } \cs_new:Npn \__wheelchart_def_coord:nn #1#2 { \__wheelchart_def_coord_aux:nn {#1} { \fp_use:c { l__wheelchart_slice_#1_#2_angle_fp } } \fp_set_eq:cN { l__wheelchart_#1~#2_x_fp } \g__wheelchart_x_coord_fp \fp_set_eq:cN { l__wheelchart_#1~#2_y_fp } \g__wheelchart_y_coord_fp } \cs_new:Npn \__wheelchart_def_gap:NN #1#2 { \fp_set:Nn #1 { (#2) * sind ( min ( \l__wheelchart_abs_half_angle_minus_new_angle_minus_gap_polar_fp , \l__wheelchart_gap_max_angle_def_fp ) ) < \l__wheelchart_gap_fp ? min ( \l__wheelchart_abs_half_angle_minus_new_angle_fp , \l__wheelchart_gap_max_angle_def_fp ) : asind ( min ( \l__wheelchart_gap_fp / ( (#2) + 1 - sign (#2) ) , 1 ) ) + \l__wheelchart_gap_polar_fp %note the min ( ... , 1 ) such that the asind is always defined %also note the + 1 - sign (#2) such that the denominator is also nonzero if #2 = 0 } } \cs_new:Npn \__wheelchart_def_macro:Nn #1#2 { \str_case:enF { \pgfkeysvalueof { / wheelchart / parse } } { { pgfmath } { \pgfmathparse {#2} \fp_set:Nn #1 { \pgfmathresult } } { l3fp } { \fp_set:Nn #1 {#2} } } { \pgfkeys { / errors / unknown~choice~value /. expanded = { parse } { \pgfkeysvalueof { / wheelchart / parse } } } } } \cs_new:Npn \__wheelchart_def_macros:n #1 { \str_case:enF { \pgfkeysvalueof { / wheelchart / parse } } { { pgfmath } { \clist_map_inline:nn {#1} { \pgfmathparse { \pgfkeysvalueof { / wheelchart / ##1 } } \fp_set:cn { l__wheelchart_\str_map_function:nN {##1} \__wheelchart_space_to_underscore:n _fp } { \pgfmathresult } } } { l3fp } { \clist_map_inline:nn {#1} { \fp_set:cn { l__wheelchart_\str_map_function:nN {##1} \__wheelchart_space_to_underscore:n _fp } { \pgfkeysvalueof { / wheelchart / ##1 } } } } } { \pgfkeys { / errors / unknown~choice~value /. expanded = { parse } { \pgfkeysvalueof { / wheelchart / parse } } } } } \cs_new:Npn \__wheelchart_def_slice_angle:nnnn #1#2#3#4 { \bool_if:NTF \l__wheelchart_plot_bool { \fp_set:cn { l__wheelchart_slice_#1_#2_angle_fp } { \fp_use:c { g__wheelchart_#3angle_fp } + ( \l__wheelchart_counter_or_clockwise_fp * ( (#4) * \fp_use:c { l__wheelchart_#1_gap_fp } + \fp_use:c { l__wheelchart_slices_#1_#2_angle_shift_fp } ) ) } } { \fp_set:cn { l__wheelchart_slice_#1_#2_angle_fp } { \fp_use:c { g__wheelchart_#3angle_fp } + ( \l__wheelchart_counter_or_clockwise_fp * ( (#4) * \fp_use:c { l__wheelchart_#1_gap_fp } + \fp_use:c { l__wheelchart_slices_#1_#2_angle_shift_fp } - asind ( \l__wheelchart_inner_radius_fp * sind ( \fp_use:c { l__wheelchart_slices_#1_#2_angle_shift_fp } ) / \l__wheelchart_outer_radius_fp ) ) ) } } } \cs_new:Npn \__wheelchart_def_slice_keys:n #1 { {%note the double {{...}} such that the contents is in a group %such that pgfkeys which are specific to the current slice are local for this slice \clist_if_in:NVT \l__wheelchart_slice_range_local_clist \WCcount { \pgfkeys { / wheelchart , slice_final /. expanded = { \exp_not:v { l__wheelchart_slice_\WCcount _keys_clist } } } \pgfkeys{ / wheelchart , slice_final_style } } #1 } } \cs_new:Npn \__wheelchart_def_WClegend: { \int_set:Nn \l__wheelchart_legend_columns_int { \fp_eval:n { ceil ( \WCtotalcount / ceil ( \WCtotalcount / ( \pgfkeysvalueof { / wheelchart / legend~columns } ) ) ) } } \cs_set:Npn \WClegend {} \tl_build_begin:N \WClegend \int_compare:nNnTF { \l__wheelchart_legend_columns_int } = { 1 } { \int_step_inline:nnn { 2 } { \WCtotalcount } { \__wheelchart_legend_append:nn {##1} { \\ } } } { \int_set:Nn \l__wheelchart_legend_rows_int { \fp_eval:n { ceil ( \WCtotalcount / \l__wheelchart_legend_columns_int ) } } \int_step_inline:nn { \l__wheelchart_legend_rows_int - 1 } { \int_step_inline:nn { \l__wheelchart_legend_columns_int - 2 } { \__wheelchart_legend_append:nn { ##1 + \l__wheelchart_legend_rows_int * ####1 } { & } } \int_compare:nNnF { ##1 + ( \l__wheelchart_legend_columns_int - 1 ) * \l__wheelchart_legend_rows_int } > { \WCtotalcount } { \__wheelchart_legend_append:nn { ##1 + ( \l__wheelchart_legend_columns_int - 1 ) * \l__wheelchart_legend_rows_int } { & } } \__wheelchart_legend_append:nn { ##1 + 1 } { \\ } } \int_step_inline:nn { \l__wheelchart_legend_columns_int - 2 } { \__wheelchart_legend_append:nn { \l__wheelchart_legend_rows_int * ( ##1 + 1 ) } { & } } \int_compare:nNnF { \l__wheelchart_legend_columns_int * \l__wheelchart_legend_rows_int } > { \WCtotalcount } { \__wheelchart_legend_append:nn { \l__wheelchart_legend_columns_int * \l__wheelchart_legend_rows_int } { & } } } \__wheelchart_legend_append:nn { 1 } { \\ }%at the moment it is unnecessary to set g__wheelchart_WCcount_counter to 1 %but this is done to be future-proof if the contents of \WClegend would be parsed in a way that prohibits the value for %g__wheelchart_WCcount_counter to be larger than \WCtotalcount \tl_build_end:N \WClegend \cs_set:Npn \WCcount { \theg__wheelchart_WCcount_counter } \cs_set:Npn \WCpercentage { \cs:w l__wheelchart_WCpercentage_\theg__wheelchart_WCcount_counter\cs_end: } \cs_set:Npn \WCpercentagerounded { \cs:w l__wheelchart_WCpercentagerounded_\theg__wheelchart_WCcount_counter\cs_end: } \str_if_eq:eeTF { \l__wheelchart_type_tl } { etoc } { \cs_set:Npn \WCetocthelinkedname { \cs:w g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_linked_name_\theg__wheelchart_WCcount_counter\cs_end: } \cs_set:Npn \WCetocthelinkednumber { \cs:w g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_linked_number_\theg__wheelchart_WCcount_counter\cs_end: } \cs_set:Npn \WCetocthelinkedpage { \cs:w g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_linked_page_\theg__wheelchart_WCcount_counter\cs_end: } \cs_set:Npn \WCetocthename { \cs:w g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_name_\theg__wheelchart_WCcount_counter\cs_end: } \cs_set:Npn \WCetocthenumber { \cs:w g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_number_\theg__wheelchart_WCcount_counter\cs_end: } \cs_set:Npn \WCetocthepage { \cs:w g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_page_\theg__wheelchart_WCcount_counter\cs_end: } \cs_set:Npn \WCetocthenumberofpages { \cs:w g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_number_of_pages_\theg__wheelchart_WCcount_counter\cs_end: } } { \clist_if_empty:NTF \l__wheelchart_header_clist { \int_step_inline:nn { \seq_count:N \l__wheelchart_list_items_seq } { \cs_set:cpn { WCvar\int_to_Alph:n {##1} } { \cs:w l__wheelchart_item_WCvar\int_to_Alph:n {##1}_\theg__wheelchart_WCcount_counter\cs_end: } } } { \int_step_inline:nn { \seq_count:N \l__wheelchart_list_items_seq } { \cs_set:cpn { \pgfkeysvalueof { / wheelchart / header~prefix } \clist_item:Nn \l__wheelchart_header_clist {##1} } { \cs:w l__wheelchart_item_\pgfkeysvalueof { / wheelchart / header~prefix } \clist_item:Nn \l__wheelchart_header_clist {##1}_\theg__wheelchart_WCcount_counter \cs_end: } } } } \setcounter { g__wheelchart_WCcount_counter } { 1 } } \cs_new:Npn \__wheelchart_diff_atan:nnnn #1#2#3#4 { Mod ( \fp_eval:n { \g__wheelchart_slices_orientation_fp * ( atand ( \fp_use:c { l__wheelchart_#3_y_fp } - \fp_use:c { l__wheelchart_#4_y_fp } , \fp_use:c { l__wheelchart_#3_x_fp } - \fp_use:c { l__wheelchart_#4_x_fp } ) - atand ( \fp_use:c { l__wheelchart_#1_y_fp } - \fp_use:c { l__wheelchart_#2_y_fp } , \fp_use:c { l__wheelchart_#1_x_fp } - \fp_use:c { l__wheelchart_#2_x_fp } ) ) } , 360 )%note the Mod 360 because for example cos(90/2)\neq cos(-270/2) } \cs_new:Npn \__wheelchart_discrete_algorithm: { \__wheelchart_def_macros:n { discrete~factor , gap~radius , samples } \__wheelchart_def_macro:Nn \l__wheelchart_outer_radius_fp { \pgfkeysvalueof { / wheelchart / outer~radius } - \fp_use:N \l__wheelchart_gap_radius_fp } \bool_if:NTF \l__wheelchart_pie_bool { \fp_set:Nn \l__wheelchart_inner_radius_fp { 0 } } { \__wheelchart_def_macro:Nn \l__wheelchart_inner_radius_fp { \pgfkeysvalueof { / wheelchart / inner~radius } + \fp_use:N \l__wheelchart_gap_radius_fp } } \int_compare:nNnT { \l__wheelchart_discrete_space_at_borders_int } = { -1 } { \pgfkeys { / errors / boolean~expected /. expanded = { discrete~space~at~borders } { \pgfkeysvalueof { / wheelchart / discrete~space~at~borders } } } } \seq_clear:N \l__wheelchart_discrete_points_seq \bool_if:NTF \l__wheelchart_plot_bool { \fp_zero:N \l__wheelchart_discrete_outer_length_fp \__wheelchart_discrete_def_coord:nn { outer } { 0 } \int_step_inline:nn { \fp_use:N \l__wheelchart_samples_fp - 1 } { \__wheelchart_discrete_def_coord:nn { outer } {##1} \fp_add:Nn \l__wheelchart_discrete_outer_length_fp { sqrt ( ( \g__wheelchart_x_coord_fp - \g__wheelchart_previous_x_coord_fp ) ^ 2 + ( \g__wheelchart_y_coord_fp - \g__wheelchart_previous_y_coord_fp ) ^ 2 ) } } \__wheelchart_discrete_def_coord:nn { inner } { \l__wheelchart_samples_fp - 1 } \fp_set:Nn \l__wheelchart_discrete_end_length_fp { sqrt ( ( \g__wheelchart_x_coord_fp - \g__wheelchart_previous_x_coord_fp ) ^ 2 + ( \g__wheelchart_y_coord_fp - \g__wheelchart_previous_y_coord_fp ) ^ 2 ) } \fp_zero:N \l__wheelchart_discrete_inner_length_fp \int_step_inline:nnnn { \fp_use:N \l__wheelchart_samples_fp - 2 } { -1 } { 0 } { \__wheelchart_discrete_def_coord:nn { inner } {##1} \fp_add:Nn \l__wheelchart_discrete_inner_length_fp { sqrt ( ( \g__wheelchart_x_coord_fp - \g__wheelchart_previous_x_coord_fp ) ^ 2 + ( \g__wheelchart_y_coord_fp - \g__wheelchart_previous_y_coord_fp ) ^ 2 ) } } \__wheelchart_discrete_def_coord:nn { outer } { 0 } \fp_set:Nn \l__wheelchart_discrete_start_length_fp { sqrt ( ( \g__wheelchart_x_coord_fp - \g__wheelchart_previous_x_coord_fp ) ^ 2 + ( \g__wheelchart_y_coord_fp - \g__wheelchart_previous_y_coord_fp ) ^ 2 ) } } { \fp_set:Nn \l__wheelchart_discrete_outer_length_fp { abs ( \l__wheelchart_total_angle_fp * deg * \l__wheelchart_outer_radius_fp ) } \fp_set:Nn \l__wheelchart_discrete_end_length_fp { abs ( \l__wheelchart_outer_radius_fp - \l__wheelchart_inner_radius_fp ) } \fp_set:Nn \l__wheelchart_discrete_inner_length_fp { abs ( \l__wheelchart_total_angle_fp * deg * \l__wheelchart_inner_radius_fp ) } %note the abs ( ... ) because \l__wheelchart_total_angle_fp can be negative %and \l__wheelchart_outer_radius_fp can be smaller than \l__wheelchart_inner_radius_fp \fp_set_eq:NN \l__wheelchart_discrete_start_length_fp \l__wheelchart_discrete_end_length_fp } \str_case:enF { \pgfkeysvalueof { / wheelchart / discrete~partitioning } } { { radius } { \int_set:Nn \l__wheelchart_discrete_partitioning_first_index_int { 1 } \int_set:Nn \l__wheelchart_discrete_partitioning_second_index_int { 2 } \fp_set_eq:NN \l__wheelchart_discrete_level_start_length_fp \l__wheelchart_discrete_inner_length_fp \fp_set_eq:NN \l__wheelchart_discrete_level_end_length_fp \l__wheelchart_discrete_outer_length_fp \fp_set_eq:NN \l__wheelchart_discrete_sublevel_start_length_fp \l__wheelchart_discrete_start_length_fp \fp_set_eq:NN \l__wheelchart_discrete_sublevel_end_length_fp \l__wheelchart_discrete_end_length_fp } { angle } { \int_set:Nn \l__wheelchart_discrete_partitioning_first_index_int { 2 } \int_set:Nn \l__wheelchart_discrete_partitioning_second_index_int { 1 } \fp_set_eq:NN \l__wheelchart_discrete_level_start_length_fp \l__wheelchart_discrete_start_length_fp \fp_set_eq:NN \l__wheelchart_discrete_level_end_length_fp \l__wheelchart_discrete_end_length_fp \fp_set_eq:NN \l__wheelchart_discrete_sublevel_start_length_fp \l__wheelchart_discrete_inner_length_fp \fp_set_eq:NN \l__wheelchart_discrete_sublevel_end_length_fp \l__wheelchart_discrete_outer_length_fp \int_set:Nn \l__wheelchart_discrete_sort_int { 3 - \l__wheelchart_discrete_sort_int } } } { \pgfkeys { / errors / unknown~choice~value /. expanded = { discrete~partitioning } { \pgfkeysvalueof { / wheelchart / discrete~partitioning } } } } \int_set:Nn \l__wheelchart_discrete_levels_int { \fp_eval:n { max ( round ( sqrt ( ( ( \l__wheelchart_discrete_sublevel_start_length_fp + \l__wheelchart_discrete_sublevel_end_length_fp ) * \l__wheelchart_discrete_factor_fp / ( \l__wheelchart_discrete_level_start_length_fp + \l__wheelchart_discrete_level_end_length_fp ) ) * \WCtotalnum ) ) , 1 ) } } \int_gzero:N \g__wheelchart_discrete_count_int \fp_zero:N \l__wheelchart_discrete_levels_sum_fp \int_step_inline:nn { \l__wheelchart_discrete_levels_int - 1 } { \fp_set:Nn \l__wheelchart_discrete_level_fp { ( ##1 - 0.5 * ( 1 + \l__wheelchart_discrete_space_at_borders_int ) ) / ( \l__wheelchart_discrete_levels_int - \l__wheelchart_discrete_space_at_borders_int ) } \fp_add:Nn \l__wheelchart_discrete_levels_sum_fp { \l__wheelchart_discrete_level_fp } \int_set:Nn \l__wheelchart_discrete_sublevels_int { \fp_eval:n { round ( ( ( ( ##1 ) * \l__wheelchart_discrete_level_start_length_fp + \l__wheelchart_discrete_levels_sum_fp * ( \l__wheelchart_discrete_level_end_length_fp - \l__wheelchart_discrete_level_start_length_fp ) ) / ( \l__wheelchart_discrete_levels_int * 0.5 * ( \l__wheelchart_discrete_level_start_length_fp + \l__wheelchart_discrete_level_end_length_fp ) ) ) * \WCtotalnum - \g__wheelchart_discrete_count_int ) } } \int_gadd:Nn \g__wheelchart_discrete_count_int { \l__wheelchart_discrete_sublevels_int } \int_compare:nNnTF { \l__wheelchart_discrete_sublevels_int } = { 1 } { \seq_put_right:Ne \l__wheelchart_discrete_points_seq { 0.5 / \fp_use:N \l__wheelchart_discrete_level_fp } } { \int_step_inline:nn { \l__wheelchart_discrete_sublevels_int } { \seq_put_right:Ne \l__wheelchart_discrete_points_seq { \fp_eval:n { ( ####1 - 0.5 * ( 1 + \l__wheelchart_discrete_space_at_borders_int ) ) / ( \l__wheelchart_discrete_sublevels_int - \l__wheelchart_discrete_space_at_borders_int ) } %the denominator is 0 if \l__wheelchart_discrete_sublevels_int = \l__wheelchart_discrete_space_at_borders_int = 1 %thus the case when \l__wheelchart_discrete_sublevels_int = 1 is treated separately above / \fp_use:N \l__wheelchart_discrete_level_fp } } } } \int_compare:nNnTF { \l__wheelchart_discrete_levels_int } = { 1 } { \fp_set:Nn \l__wheelchart_discrete_level_fp { 0.5 } } { \fp_set:Nn \l__wheelchart_discrete_level_fp { 1 - 0.5 * ( 1 - \l__wheelchart_discrete_space_at_borders_int ) / ( \l__wheelchart_discrete_levels_int - \l__wheelchart_discrete_space_at_borders_int ) } } \int_set:Nn \l__wheelchart_discrete_sublevels_int { \fp_eval:n { round ( \WCtotalnum - \g__wheelchart_discrete_count_int ) } } \int_compare:nNnTF { \l__wheelchart_discrete_sublevels_int } = { 1 } { \seq_put_right:Ne \l__wheelchart_discrete_points_seq { 0.5 / \fp_use:N \l__wheelchart_discrete_level_fp } } { \int_step_inline:nn { \l__wheelchart_discrete_sublevels_int } { \seq_put_right:Ne \l__wheelchart_discrete_points_seq { \fp_eval:n { ( ##1 - 0.5 * ( 1 + \l__wheelchart_discrete_space_at_borders_int ) ) / ( \l__wheelchart_discrete_sublevels_int - \l__wheelchart_discrete_space_at_borders_int ) } / \fp_use:N \l__wheelchart_discrete_level_fp } } } \seq_sort:Nn \l__wheelchart_discrete_points_seq { \seq_set_split:Nnn \l__wheelchart_discrete_coefficients_first_seq { / } {##1} \seq_set_split:Nnn \l__wheelchart_discrete_coefficients_second_seq { / } {##2} \fp_compare:nNnTF { \seq_item:Nn \l__wheelchart_discrete_coefficients_first_seq { \l__wheelchart_discrete_sort_int } } > { \seq_item:Nn \l__wheelchart_discrete_coefficients_second_seq { \l__wheelchart_discrete_sort_int } } { \sort_return_swapped: } { \sort_return_same: } } \int_gzero:N \g__wheelchart_discrete_count_int \__wheelchart_for_loop:n { \pgfkeysvalueof { / wheelchart / before~slices } \int_step_inline:nn { \fp_eval:n { round ( \l__wheelchart_value_fp ) } }%note that \fp_eval:n { round ( ... ) } is necessary %even when the value is an integer because if parse=pgfmath then .0 is added and then %\int_step_inline:nn { \fp_use:N \l__wheelchart_value_fp } would give the messages %Missing character: There is no . in font nullfont! Missing character: There is no 0 in font nullfont! { \int_gincr:N \g__wheelchart_discrete_count_int \cs_set:Npe \WCcountdiscrete { \int_use:N \g__wheelchart_discrete_count_int } \seq_set_split:Nne \l__wheelchart_discrete_coefficients_first_seq { / } { \seq_item:Nn \l__wheelchart_discrete_points_seq { \g__wheelchart_discrete_count_int } } %Naturally, an error occurs if the sum of the rounded values of the key value is %greater than the rounded value of \WCtotalnum. %For example if there are 2 values 1.6 and 1.7 then these numbers are 4 and 3 and then there is no 4-th item in the list. %However only positive integer values make practical sense for this diagram. \pic [ / wheelchart / slices_style ] at ( $ ( \__wheelchart_inner_plot:nn { \fp_eval:n { \l__wheelchart_start_angle_fp + \l__wheelchart_counter_or_clockwise_fp * \l__wheelchart_total_angle_fp * ( \seq_item:Nn \l__wheelchart_discrete_coefficients_first_seq { \l__wheelchart_discrete_partitioning_first_index_int } ) } } { \fp_use:N \l__wheelchart_inner_radius_fp } ) ! { \seq_item:Nn \l__wheelchart_discrete_coefficients_first_seq { \l__wheelchart_discrete_partitioning_second_index_int } } ! ( \__wheelchart_outer_plot:nn { \fp_eval:n { \l__wheelchart_start_angle_fp + \l__wheelchart_counter_or_clockwise_fp * \l__wheelchart_total_angle_fp * ( \seq_item:Nn \l__wheelchart_discrete_coefficients_first_seq { \l__wheelchart_discrete_partitioning_first_index_int } ) } } { \fp_use:N \l__wheelchart_outer_radius_fp } ) $ ) { code = { \pgfkeysvalueof { / wheelchart / discrete~pic } } } ; } \pgfkeysvalueof { / wheelchart / after~slices } } } \cs_new:Npn \__wheelchart_discrete_def_coord:nn #1#2 { \fp_gset_eq:NN \g__wheelchart_previous_x_coord_fp \g__wheelchart_x_coord_fp \fp_gset_eq:NN \g__wheelchart_previous_y_coord_fp \g__wheelchart_y_coord_fp \__wheelchart_def_coord_aux:nn {#1} { \fp_eval:n { \l__wheelchart_start_angle_fp + ( ( #2 ) / ( \l__wheelchart_samples_fp - 1 ) ) * \l__wheelchart_counter_or_clockwise_fp * \l__wheelchart_total_angle_fp } } } \cs_new:Npn \__wheelchart_for_loop:n #1 { \fp_gset_eq:NN \g__wheelchart_angle_fp \l__wheelchart_start_angle_fp \__wheelchart_for_loop_initial:n { \__wheelchart_def_slice_keys:n { \fp_set_eq:Nc \l__wheelchart_value_fp { l__wheelchart_value_\WCcount _fp } \cs_set_eq:Nc \WCpercentage { l__wheelchart_WCpercentage_\WCcount } \cs_set_eq:Nc \WCpercentagerounded { l__wheelchart_WCpercentagerounded_\WCcount } \fp_gset:Nn \g__wheelchart_new_angle_fp { \WCcount == \WCtotalcount ? \l__wheelchart_start_angle_fp + \l__wheelchart_counter_or_clockwise_fp * \l__wheelchart_total_angle_fp : \g__wheelchart_angle_fp + ( \l__wheelchart_counter_or_clockwise_fp * \l__wheelchart_value_fp * ( \l__wheelchart_total_angle_fp / \WCtotalnum ) ) } \__wheelchart_def_macros:n { data~angle~pos , gap , gap~max~angle , gap~polar , gap~radius , samples , slices~inner~end~angle~shift , slices~inner~start~angle~shift , slices~outer~end~angle~shift , slices~outer~start~angle~shift } \__wheelchart_def_macro:Nn \l__wheelchart_outer_radius_fp { \pgfkeysvalueof { / wheelchart / outer~radius } - \fp_use:N \l__wheelchart_gap_radius_fp } \bool_if:NTF \l__wheelchart_pie_bool { \fp_set:Nn \l__wheelchart_inner_radius_fp { 0 } } { \__wheelchart_def_macro:Nn \l__wheelchart_inner_radius_fp { \pgfkeysvalueof { / wheelchart / inner~radius } + \fp_use:N \l__wheelchart_gap_radius_fp } } \fp_set_eq:NN \l__wheelchart_inner_radius_orig_fp \l__wheelchart_inner_radius_fp \fp_set:Nn \l__wheelchart_abs_half_angle_minus_new_angle_fp { abs ( \g__wheelchart_angle_fp - \g__wheelchart_new_angle_fp ) / 2 } \fp_set:Nn \l__wheelchart_abs_half_angle_minus_new_angle_minus_gap_polar_fp { \l__wheelchart_abs_half_angle_minus_new_angle_fp - \l__wheelchart_gap_polar_fp } \bool_if:NTF \l__wheelchart_plot_bool { \fp_set_eq:NN \l__wheelchart_outer_gap_fp \l__wheelchart_gap_polar_fp \fp_set_eq:NN \l__wheelchart_inner_gap_fp \l__wheelchart_gap_polar_fp } { \fp_set:Nn \l__wheelchart_gap_max_angle_def_fp { \l__wheelchart_inner_radius_fp > 0 ? 90 : ( sind ( \l__wheelchart_abs_half_angle_minus_new_angle_minus_gap_polar_fp ) < 0.001 ? ( 90 < \l__wheelchart_gap_max_angle_fp && \l__wheelchart_gap_max_angle_fp < 180 ? \l__wheelchart_gap_max_angle_fp : 90 ) : ( \l__wheelchart_gap_max_angle_fp < 90 || \l__wheelchart_gap_max_angle_fp > 180 ? 180 : \l__wheelchart_gap_max_angle_fp ) ) } \__wheelchart_def_gap:NN \l__wheelchart_outer_gap_fp \l__wheelchart_outer_radius_fp \__wheelchart_def_gap:NN \l__wheelchart_inner_gap_fp \l__wheelchart_inner_radius_fp \fp_compare:nNnT { \l__wheelchart_abs_half_angle_minus_new_angle_minus_gap_polar_fp } > { 0.01 } { \fp_set:Nn \l__wheelchart_inner_radius_fp { max ( \l__wheelchart_gap_fp / sind ( min ( \l__wheelchart_abs_half_angle_minus_new_angle_minus_gap_polar_fp , \l__wheelchart_gap_max_angle_def_fp ) ) , \l__wheelchart_inner_radius_fp ) } } } \__wheelchart_def_slice_angle:nnnn { inner } { end } { new_ } { -1 } \__wheelchart_def_slice_angle:nnnn { inner } { start } {} { 1 } \__wheelchart_def_slice_angle:nnnn { outer } { end } { new_ } { -1 } \__wheelchart_def_slice_angle:nnnn { outer } { start } {} { 1 } \__wheelchart_def_angle:nnnN { 0.5 } { 0 } { 0 } \WCmidangle \__wheelchart_def_macros:n { data~angle~shift , data~sep } \__wheelchart_def_angle:nnnN { \l__wheelchart_data_angle_pos_fp } { \l__wheelchart_data_angle_shift_fp } { \l__wheelchart_data_sep_fp } \WCdataangle \__wheelchart_def_macros:n { explode } \pgfkeysvalueof { / wheelchart / for~loop~start }%this must be placed after the definition of macros such as \WCpercentage %such that these macros can be used in the key for loop start \begin { scope } [ shift = { ( \WCmidangle \c_colon_str \fp_use:N \l__wheelchart_explode_fp ) } , / wheelchart / slices_scope ] #1 \end { scope } \fp_gset_eq:NN \g__wheelchart_angle_fp \g__wheelchart_new_angle_fp \pgfkeysvalueof { / wheelchart / for~loop~end } } } } \cs_new:Npn \__wheelchart_for_loop_initial:n #1 { \str_case:en { \l__wheelchart_type_tl } { { default } { \clist_if_empty:NTF \l__wheelchart_header_clist { \int_step_inline:nn { \WCtotalcount } { \cs_set:Npe \WCcount {##1} \int_step_inline:nn { \seq_count:N \l__wheelchart_list_items_seq } { \cs_set_eq:cc { WCvar\int_to_Alph:n {####1} } { l__wheelchart_item_WCvar\int_to_Alph:n {####1}_##1 } } #1 } } { \int_step_inline:nn { \WCtotalcount } { \cs_set:Npe \WCcount {##1} \int_step_inline:nn { \seq_count:N \l__wheelchart_list_items_seq } { \cs_set_eq:cc { \pgfkeysvalueof { / wheelchart / header~prefix } \clist_item:Nn \l__wheelchart_header_clist {####1} } { l__wheelchart_item_\pgfkeysvalueof { / wheelchart / header~prefix } \clist_item:Nn \l__wheelchart_header_clist {####1}_##1 } } #1 } } } { totalcount } { \int_step_inline:nn { \WCtotalcount } { \cs_set:Npe \WCcount {##1} #1 } } { etoc } { \int_step_inline:nn { \WCtotalcount } { \cs_set:Npe \WCcount {##1} \cs_set_eq:Nc \WCetocthelinkedname { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_linked_name_##1 } \cs_set_eq:Nc \WCetocthelinkednumber { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_linked_number_##1 } \cs_set_eq:Nc \WCetocthelinkedpage { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_linked_page_##1 } \cs_set_eq:Nc \WCetocthename { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_name_##1 } \cs_set_eq:Nc \WCetocthenumber { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_number_##1 } \cs_set_eq:Nc \WCetocthepage { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_page_##1 } \cs_set_eq:Nc \WCetocthenumberofpages { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_number_of_pages_##1 } #1 } } } } \cs_new:Npn \__wheelchart_if_text:nn #1#2 { %https://tex.stackexchange.com/questions/42280/expand-away-empty-macros-within-ifthenelse %https://tex.stackexchange.com/questions/44919/proper-way-to-detect-empty-blank-text \begin { pgfinterruptpicture } %https://tex.stackexchange.com/questions/459853/savebox-within-tikzpicture-results-in-an-empty-savebox \hbox_gset:Nn \g__wheelchart_if_text_box { \pgfkeysvalueof { / wheelchart / #1 } } \end { pgfinterruptpicture } \dim_compare:nNnT { \box_wd:N \g__wheelchart_if_text_box } > { 0 pt } { {#2} } } \cs_new:Npn \__wheelchart_initial:n #1 { \str_case:en { \l__wheelchart_type_tl } { { default } { \tl_if_empty:nTF {#1} { \cs_set:Npn \WCtotalcount { 0 } } { \use:c { seq_set_split:Ne\l__wheelchart_expand_list_tl } \l__wheelchart_list_seq { \pgfkeysvalueof { / wheelchart / separator~rows } } {#1} \cs_set:Npe \WCtotalcount { \seq_count:N \l__wheelchart_list_seq } \seq_map_indexed_inline:Nn \l__wheelchart_list_seq { \use:c { seq_set_split:Ne\l__wheelchart_expand_list_items_tl } \l__wheelchart_list_items_seq { \pgfkeysvalueof { / wheelchart / separator~columns } } {##2} %make sure that the namespace l__wheelchart_item_ below is unique \clist_if_empty:NTF \l__wheelchart_header_clist { \seq_map_indexed_inline:Nn \l__wheelchart_list_items_seq { \cs_set:cpn { l__wheelchart_item_WCvar\int_to_Alph:n {####1}_##1 } {####2} } } { \seq_map_indexed_inline:Nn \l__wheelchart_list_items_seq { \cs_set:cpn { l__wheelchart_item_\pgfkeysvalueof { / wheelchart / header~prefix } \clist_item:Nn \l__wheelchart_header_clist {####1}_##1 } {####2} } } } } } { totalcount } { \cs_set:Npe \WCtotalcount { \fp_use:N \l__wheelchart_total_count_fp } \cs_set:Npn \WCvarA { 1 } \cs_set:Npn \WCvarB {} \cs_set:Npn \WCvarC {} } { etoc } { \bool_if:NTF \l__wheelchart_etoc_use_name_bool { \int_if_exist:cTF { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } { \cs_set:Npe \WCtotalcount { \int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } } { \cs_set:Npn \WCtotalcount { 0 } } } { \@ifpackageloaded { etoc } {} { \PackageError { wheelchart } { The~package~etoc~must~be~loaded~to~use~the~key~etoc~level } {} } \etocsetlevel { part } { 0 } \etocsetlevel { chapter } { 0 } \etocsetlevel { section } { 0 } \etocsetlevel { subsection } { 0 } \etocsetlevel { subsubsection } { 0 } \etocsetlevel { paragraph } { 0 } \etocsetlevel { subparagraph } { 0 } \etocsetlevel { \l__wheelchart_etoc_level_tl } { -1 }%these level changes are local to the current group \etocsetnexttocdepth { -1 }%only for the next toc \etocsetstyle { \l__wheelchart_etoc_level_tl } {} {} { \int_compare:nNnT { \int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } > { 0 } { \cs_gset:cpe { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_number_of_pages_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } { \int_eval:n { \etocthepage - \cs:w g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_page_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } \cs_end: } } } \int_gincr:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } \cs_gset_eq:cN { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_linked_name_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } \etocthelinkedname \cs_gset_eq:cN { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_linked_number_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } \etocthelinkednumber \cs_gset_eq:cN { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_linked_page_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } \etocthelinkedpage \cs_gset_eq:cN { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_name_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } \etocthename \cs_gset_eq:cN { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_number_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } \etocthenumber \cs_gset_eq:cN { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_page_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } \etocthepage } {} \int_gzero_new:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } \pgfkeysvalueof { / wheelchart / etoc~code } \int_compare:nNnT { \int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } > { 0 } { \cs_gset:cpe { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_number_of_pages_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } { \int_eval:n { \l__wheelchart_etoc_count_total_pages_int + 1 - \cs:w g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _the_page_\int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } \cs_end: } } } \cs_set:Npe \WCtotalcount { \int_use:c { g__wheelchart_etoc_item_\l__wheelchart_etoc_name_tl _count_int } } } } } \cs_set:Npn \WCtotalnum { 0 } \__wheelchart_for_loop_initial:n { \__wheelchart_def_slice_keys:n { \__wheelchart_def_macros:n { value } \fp_gset_eq:NN \g__wheelchart_value_global_fp \l__wheelchart_value_fp } \fp_zero_new:c { l__wheelchart_value_\WCcount _fp } \fp_set_eq:cN { l__wheelchart_value_\WCcount _fp } \g__wheelchart_value_global_fp \cs_set:Npe \WCtotalnum { \fp_eval:n { \WCtotalnum + \g__wheelchart_value_global_fp } } } \int_step_inline:nn { \WCtotalcount } { \cs_set:cpe { l__wheelchart_WCpercentage_##1 } { \fp_eval:n { \fp_use:c { l__wheelchart_value_##1_fp } / ( \WCtotalnum / 100 ) } } \cs_set:cpe { l__wheelchart_WCpercentagerounded_##1 } { \fp_eval:n { round ( \cs:w l__wheelchart_WCpercentage_##1\cs_end: , \pgfkeysvalueof { / wheelchart / perc~precision } ) } } } } \cs_new:Npn \__wheelchart_inner_plot:nn #1#2 { {#1} \c_colon_str {#2} } \cs_new:Npn \__wheelchart_legend_append:nn #1#2 { \tl_build_put_right:NV \WClegend \l__wheelchart_legend_row_tl%note the V specifier such that \WClegend can also be combined %with an S column of the package siunitx and such that \WClegend can be used in a tblr environment of the package tabularray %and then the option expand=\WClegend needs to be given to the tblr environment \tl_build_put_right:Nn \WClegend { \protect \setcounter { g__wheelchart_WCcount_counter } }%note the \protect for in case that %\WClegend would be parsed in a particular way %note that the counter g__wheelchart_WCcount_counter is defined globally and at the end of the previous \l__wheelchart_legend_row_tl %such that this value is defined and has the right value at the start of the next \l__wheelchart_legend_row_tl %if \WClegend is used in a tblr environment of the package tabularray then \UseTblrLibrary{counter} is required \tl_build_put_right:Ne \WClegend { { \int_eval:n {#1} } } \tl_build_put_right:Nn \WClegend {#2} } \cs_new:Npn \__wheelchart_outer_plot:nn #1#2 { {#1} \c_colon_str {#2} } \cs_new:Npn \__wheelchart_slices_arc:nnnnnn #1#2#3#4#5#6 { { [ / utils / exec = { \__wheelchart_def_macro:Nn \l__wheelchart_slices_arc_A_fp {#1} #6 \fp_set:Nn \l__wheelchart_slices_arc_A_abs_fp { abs ( \l__wheelchart_slices_arc_A_fp ) } \fp_compare:nNnF { \l__wheelchart_slices_arc_A_abs_fp } < { 0.01 } { \__wheelchart_def_macro:Nn \l__wheelchart_slices_arc_B_fp {#2} \fp_set:Nn \l__wheelchart_slices_arc_rotate_fp { atand ( \fp_use:c { l__wheelchart_#3_y_fp } - \fp_use:c { l__wheelchart_#4_y_fp } , \fp_use:c { l__wheelchart_#3_x_fp } - \fp_use:c { l__wheelchart_#4_x_fp } ) } \fp_set:Nn \l__wheelchart_slices_arc_coord_fp { \l__wheelchart_slices_arc_A_fp < 0 && \l__wheelchart_slices_arc_B_fp < 0 ? 0 : \l__wheelchart_slices_arc_B_fp } \fp_set:Nn \l__wheelchart_slices_arc_angle_fp { \l__wheelchart_slices_arc_A_fp < 0 && \l__wheelchart_slices_arc_B_fp < 0 ? acosd ( 2 / ( ( min ( \l__wheelchart_slices_arc_B_fp , 0 ) - 1 ) * ( ( 1 / \l__wheelchart_slices_arc_A_fp ) + \l__wheelchart_slices_arc_A_fp ) ) ) : atand ( ( \l__wheelchart_slices_arc_A_fp - ( 1 / \l__wheelchart_slices_arc_A_fp ) ) / 2 ) }%note the min ( \l__wheelchart_slices_arc_B_fp , 0 ) such that the acosd is always defined } } ] \fp_compare:nNnTF { \l__wheelchart_slices_arc_A_abs_fp } < { 0.01 } {#5} { \fp_compare:nNnT { \l__wheelchart_slices_arc_B_fp } < { 1 } { \fp_compare:nNnF { \l__wheelchart_slices_arc_coord_fp } = { 0 } { -- ( $ ( \fp_use:c { l__wheelchart_#3_x_fp } , \fp_use:c { l__wheelchart_#3_y_fp } ) ! { \fp_eval:n { \l__wheelchart_slices_arc_coord_fp / 2 } } ! ( \fp_use:c { l__wheelchart_#4_x_fp } , \fp_use:c { l__wheelchart_#4_y_fp } ) $ ) } arc [ start~angle = { \fp_eval:n { \l__wheelchart_slices_arc_rotate_fp - \g__wheelchart_slices_orientation_fp * \l__wheelchart_slices_arc_angle_fp } } , end~angle = { \fp_eval:n { \l__wheelchart_slices_arc_rotate_fp + \g__wheelchart_slices_orientation_fp * ( sign ( \l__wheelchart_slices_arc_A_fp ) * 180 + \l__wheelchart_slices_arc_angle_fp ) } } , radius = { \fp_eval:n { 0.25 * ( 1 - \l__wheelchart_slices_arc_B_fp ) * abs ( ( 1 / \l__wheelchart_slices_arc_A_fp ) + \l__wheelchart_slices_arc_A_fp ) * sqrt ( ( \fp_use:c { l__wheelchart_#3_x_fp } - \fp_use:c { l__wheelchart_#4_x_fp } ) ^ 2 + ( \fp_use:c { l__wheelchart_#3_y_fp } - \fp_use:c { l__wheelchart_#4_y_fp } ) ^ 2 ) } } ] } \fp_compare:nNnF { \l__wheelchart_slices_arc_coord_fp } = { 0 } {#5} } } } \cs_new:Npn \__wheelchart_slices_arrow:nnnnn #1#2#3#4#5 { { [ / utils / exec = { \__wheelchart_def_macro:Nn \l__wheelchart_slices_arrow_A_fp {#1} \fp_compare:nNnF { \l__wheelchart_slices_arrow_A_fp } = { 0 } { \__wheelchart_def_macro:Nn \l__wheelchart_slices_arrow_B_fp {#2} \fp_set:Nn \l__wheelchart_slices_arrow_coord_fp { \l__wheelchart_slices_arrow_A_fp < 0 && \l__wheelchart_slices_arrow_B_fp < 0 ? 0 : \l__wheelchart_slices_arrow_B_fp } } } ] \fp_compare:nNnTF { \l__wheelchart_slices_arrow_A_fp } = { 0 } {#5} { \fp_compare:nNnT { \l__wheelchart_slices_arrow_B_fp } < { 1 } { \fp_compare:nNnF { \l__wheelchart_slices_arrow_coord_fp } = { 0 } { -- ( $ ( \fp_use:c { l__wheelchart_#3_x_fp } , \fp_use:c { l__wheelchart_#3_y_fp } ) ! { \fp_eval:n { \l__wheelchart_slices_arrow_coord_fp / 2 } } ! ( \fp_use:c { l__wheelchart_#4_x_fp } , \fp_use:c { l__wheelchart_#4_y_fp } ) $ ) } -- ( \fp_eval:n { ( \fp_use:c { l__wheelchart_#3_x_fp } + \fp_use:c { l__wheelchart_#4_x_fp } + ( \g__wheelchart_slices_orientation_fp * ( \l__wheelchart_slices_arrow_coord_fp - 1 ) * \l__wheelchart_slices_arrow_A_fp * ( \fp_use:c { l__wheelchart_#3_y_fp } - \fp_use:c { l__wheelchart_#4_y_fp } ) ) ) / 2 } , \fp_eval:n { ( \fp_use:c { l__wheelchart_#3_y_fp } + \fp_use:c { l__wheelchart_#4_y_fp } + ( \g__wheelchart_slices_orientation_fp * ( \l__wheelchart_slices_arrow_coord_fp - 1 ) * \l__wheelchart_slices_arrow_A_fp * ( \fp_use:c { l__wheelchart_#4_x_fp } - \fp_use:c { l__wheelchart_#3_x_fp } ) ) ) / 2 } ) \fp_compare:nNnF { \l__wheelchart_slices_arrow_coord_fp } = { 0 } { -- ( $ ( \fp_use:c { l__wheelchart_#4_x_fp } , \fp_use:c { l__wheelchart_#4_y_fp } ) ! { \fp_eval:n { \l__wheelchart_slices_arrow_coord_fp / 2 } } ! ( \fp_use:c { l__wheelchart_#3_x_fp } , \fp_use:c { l__wheelchart_#3_y_fp } ) $ ) } } #5 } } } \cs_new:Npn \__wheelchart_slices_to:nn #1#2 { to [ out = { \fp_eval:n { - \g__wheelchart_slices_orientation_fp * sign ( \l__wheelchart_coord_determinant_fp ) * (#1) } } , in = { \fp_eval:n { \g__wheelchart_slices_orientation_fp * sign ( \l__wheelchart_coord_determinant_fp ) * ( (#2) - 180 ) } } , relative ] } \cs_new:Npn \__wheelchart_space_to_underscore:n #1 { \str_if_eq:nnTF {#1} { ~ } { _ } {#1} } %%> \subsection{Pgfkeys} \pgfkeys { / wheelchart /. is~family , / wheelchart , after~slices /. initial = {} , anchor~xsep /. initial = 5 , anchor~ysep /. initial = 5 , arc /. style = { bool_set_true = \l__wheelchart_arc_bool , arc_style /. style = {#1} } , arc_style /. style = {} , arc~around~text /. default = true ,%this key is not set up with /.is choice or \bool_set:Nn %such that for example \WCvarA can be used as value for this key arc~around~text /. initial = false , arc~data /. initial = {} , arc~data~align /. code = { \tl_set:Nn \l__wheelchart_arc_data_align_tl {#1} } ,%this key is not set up with /.is choice %such that for example \WCvarA can be used as value for this key arc~data~align = center , arc~data~angle~pos /. initial = 0.5 , arc~data~angle~shift /. initial = 0 , arc~data~dir /. initial = 1 , arc~data~pos /. initial = 1 , arc~data~sep /. initial = 1 ex / 1 cm , arc~data~style /. style = { arc_data_style /. style = {#1} } , arc_data_style /. style = {} , arc~first~half /. style = { arc_first_half /. style = {#1} } , arc_first_half /. style = {} , arc~pos /. initial = 1 , arc~second~half /. style = { arc_second_half /. style = {#1} } , arc_second_half /. style = {} , arc~sep /. initial = 1 ex / 1 cm , at /. initial = { ( 0 , 0 ) } , before~slices /. initial = {} , bool_set_true /. code = { \bool_set_true:N #1 } , caption /. initial = {} , caption~left /. initial = {} , caption~left~sep /. initial = 0.5 , caption~left~style /. style = { caption~left_style /. style = {#1} } , caption~left_style /. style = {} , caption~sep /. initial = 0.5 , caption~style /. style = { caption_style /. style = {#1} } , caption_style /. style = {} , contour /. style = { bool_set_true = \l__wheelchart_contour_bool , contour_style /. style = {#1} } , contour_style /. style = {} , counterclockwise /. is~choice , counterclockwise / false /. code = { \fp_set:Nn \l__wheelchart_counter_or_clockwise_fp { -1 } } , counterclockwise / false /. value~forbidden , counterclockwise / true /. code = { \fp_set:Nn \l__wheelchart_counter_or_clockwise_fp { 1 } } , counterclockwise / true /. value~forbidden , counterclockwise /. default = true , counterclockwise = false , data /. initial = { \WCvarC } , data~angle~pos /. initial = 0.5 , data~angle~shift /. initial = 0 , data~pos /. initial = 1 , data~sep /. initial = 0.2 , data~style /. style = { data_style /. style = {#1} } , data_style /. style = {} , discrete /. is~choice , discrete / false /. code = { \bool_set_false:N \l__wheelchart_discrete_bool } , discrete / false /. value~forbidden , discrete / true /. code = { \bool_set_true:N \l__wheelchart_discrete_bool } , discrete / true /. value~forbidden , discrete /. default = true , discrete = false , discrete~factor /. initial = 1 , discrete~partitioning /. initial = radius , discrete~pic /. initial = {} , discrete~sort /. is~choice , discrete~sort / angle /. code = { \int_set:Nn \l__wheelchart_discrete_sort_int { 1 } } , discrete~sort / angle /. value~forbidden , discrete~sort / radius /. code = { \int_set:Nn \l__wheelchart_discrete_sort_int { 2 } } , discrete~sort / radius /. value~forbidden , discrete~sort = angle , discrete~space~at~borders /. is~choice ,%this key is not set up with /.is if because an initial value is unwanted for this key discrete~space~at~borders / false /. code = { \int_set:Nn \l__wheelchart_discrete_space_at_borders_int { 1 } } , discrete~space~at~borders / false /. value~forbidden , discrete~space~at~borders / true /. code = { \int_set:Nn \l__wheelchart_discrete_space_at_borders_int { 0 } } , discrete~space~at~borders / true /. value~forbidden , discrete~space~at~borders /. default = true , domain /. style~args /. expanded = { ##1 \c_colon_str ##2 } { counterclockwise , start~angle = {##1} , total~angle = { (##2) - (##1) } } , etoc~code /. initial = { \tableofcontents } , etoc~count~total~pages /. code = { \int_set:Nn \l__wheelchart_etoc_count_total_pages_int {#1} } , etoc~level /. code = { \tl_set:Nn \l__wheelchart_type_tl { etoc } \tl_set:Nn \l__wheelchart_etoc_level_tl {#1} } , etoc~name /. code = { \tl_set:Nn \l__wheelchart_etoc_name_tl {#1} } , etoc~name = , etoc~use~name /. code = { \tl_set:Nn \l__wheelchart_etoc_name_tl {#1} \tl_set:Nn \l__wheelchart_type_tl { etoc } \bool_set_true:N \l__wheelchart_etoc_use_name_bool } , expand~list /. is~choice , expand~list / false /. code = { \tl_set:Nn \l__wheelchart_expand_list_tl { n } } , expand~list / false /. value~forbidden , expand~list / once /. code = { \tl_set:Nn \l__wheelchart_expand_list_tl { o } } , expand~list / once /. value~forbidden , expand~list / true /. code = { \tl_set:Nn \l__wheelchart_expand_list_tl { e } } , expand~list / true /. value~forbidden , expand~list = once , expand~list~items /. is~choice , expand~list~items / false /. code = { \tl_set:Nn \l__wheelchart_expand_list_items_tl { n } } , expand~list~items / false /. value~forbidden , expand~list~items / once /. code = { \tl_set:Nn \l__wheelchart_expand_list_items_tl { o } } , expand~list~items / once /. value~forbidden , expand~list~items / true /. code = { \tl_set:Nn \l__wheelchart_expand_list_items_tl { e } } , expand~list~items / true /. value~forbidden , expand~list~items = false , explode /. initial = 0 , explode /. default = 0.2 , for~loop~end /. initial = {} , for~loop~start /. initial = {} , gap /. initial = 0 , gap /. default = 0.05 , gap~max~angle /. initial = 180 , gap~polar /. initial = 0 , gap~polar /. default = 1 , gap~radius /. initial = 0 , gap~radius /. default = 0.05 ,%the same default value as for gap header /. code = { \clist_set:Nn \l__wheelchart_header_clist {#1} } , header~prefix /. initial = WC , inner~data /. initial = {} , inner~data~angle~pos /. initial = 0.5 , inner~data~angle~shift /. initial = 0 , inner~data~pos /. initial = 0 , inner~data~sep /. initial = 0.2 , inner~data~style /. style = { inner_data_style /. style = {#1} } , inner_data_style /. style = {} , inner~plot /. code = { \bool_set_true:N \l__wheelchart_plot_bool \cs_set:Npn \__wheelchart_inner_plot:nn ##1##2 {#1} \tl_set:Nn \l__wheelchart_slices_inner_tl { -- plot [ domain = \fp_use:N \l__wheelchart_slice_inner_end_angle_fp \c_colon_str \fp_use:N \l__wheelchart_slice_inner_start_angle_fp , samples = \fp_use:N \l__wheelchart_samples_fp , variable = \l__wheelchart_inner_plot_variable_fp , / wheelchart / inner_plot_style ] ( \__wheelchart_inner_plot:nn { \l__wheelchart_inner_plot_variable_fp } { \fp_use:N \l__wheelchart_inner_radius_fp } ) } } , inner~plot~style /. style = { inner_plot_style /. style = {#1} } , inner_plot_style /. style = {} , inner~radius /. initial = 2 , legend /. initial = {} , legend~columns /. initial = 1 , legend~entry /. initial = {} , legend~only /. code = { \bool_set:Nn \l__wheelchart_legend_only_bool { \cs:w c_#1_bool\cs_end: } } , legend~only /. default = true , legend~only = false , legend~row /. code = { \bool_set_true:N \l__wheelchart_legend_row_bool \tl_set:Nn \l__wheelchart_legend_row_tl {#1} } , lines /. initial = 0 , lines /. default = 1 , lines~angle~pos /. initial = 0.5 , lines~angle~shift /. initial = 0 , lines~ext /. initial = 0 , lines~ext /. default = 0.5 , lines~ext~bottom~dir /. code = { \int_set_eq:Nc \l__wheelchart_lines_ext_bottom_dir_int { c__wheelchart_lines_ext_dir_#1_int } } , lines~ext~bottom~dir = right , lines~ext~dir /. code = { \bool_set_true:N \l__wheelchart_lines_ext_dir_bool \int_set_eq:Nc \l__wheelchart_lines_ext_dir_int { c__wheelchart_lines_ext_dir_#1_int } } , lines~ext~dirsep /. initial = 0 , lines~ext~fixed /. default = true ,%this key is not set up with /.is choice or \bool_set:Nn %such that for example \WCvarA can be used as value for this key lines~ext~fixed /. initial = false , lines~ext~fixed~left /. initial = { \fp_eval:n { \l__wheelchart_lines_ext_dir_int * ( \l__wheelchart_outer_radius_fp + \l__wheelchart_lines_sep_fp + \l__wheelchart_lines_fp + \l__wheelchart_lines_ext_fp ) } } , lines~ext~fixed~right /. initial = { \fp_eval:n { \l__wheelchart_lines_ext_dir_int * ( \l__wheelchart_outer_radius_fp + \l__wheelchart_lines_sep_fp + \l__wheelchart_lines_fp + \l__wheelchart_lines_ext_fp ) } } , lines~ext~left~anchor /. initial = mid~east , lines~ext~right~anchor /. initial = mid~west , lines~ext~top~dir /. code = { \int_set_eq:Nc \l__wheelchart_lines_ext_top_dir_int { c__wheelchart_lines_ext_dir_#1_int } } , lines~ext~top~dir = right , lines~pos /. initial = 1 , lines~sep /. initial = 0.2 , lines~style /. style = { lines_style /. style = {#1} } , lines_style /. style = {} , middle /. initial = {} , middle~fill /. style = { bool_set_true = \l__wheelchart_middle_fill_bool , middle_fill /. style = {#1} } , middle_fill /. style = {} , middle~style /. style = { middle_style /. style = {#1} } , middle_style /. style = {} , name /. code = { \tl_gset:Ne \g__wheelchart_name_tl {#1} } , name = wheelchart@name , outer~plot /. code = { \bool_set_true:N \l__wheelchart_plot_bool \cs_set:Npn \__wheelchart_outer_plot:nn ##1##2 {#1} \tl_set:Nn \l__wheelchart_slices_outer_tl { -- plot [ domain = \fp_use:N \l__wheelchart_slice_outer_start_angle_fp \c_colon_str \fp_use:N \l__wheelchart_slice_outer_end_angle_fp , samples = \fp_use:N \l__wheelchart_samples_fp , variable = \l__wheelchart_outer_plot_variable_fp , / wheelchart / outer_plot_style ] ( \__wheelchart_outer_plot:nn { \l__wheelchart_outer_plot_variable_fp } { \fp_use:N \l__wheelchart_outer_radius_fp } ) } } , outer~plot~style /. style = { outer_plot_style /. style = {#1} } , outer_plot_style /. style = {} , outer~radius /. initial = 3 , parse /. initial = pgfmath , perc~precision /. initial = 0 , pie /. code = { \bool_set:Nn \l__wheelchart_pie_bool { \cs:w c_#1_bool\cs_end: } } , pie /. default = true , pie = false , plot /. style = { inner~plot = {#1} , outer~plot = {#1} } , plot~style /. style = { inner~plot~style = {#1} , outer~plot~style = {#1} } , radius /. style~2~args = { inner~radius = {#1} , outer~radius = {#2} } , samples /. initial = 25 ,%the same number as /tikz/samples separator~columns /. initial = / , separator~rows /. initial = { , } , slice_final /. style = { slice_final_style /. style = {#1} } , slice_final_style /. style = {} , slices /. code = { \bool_set_true:N \l__wheelchart_slices_bool \tl_set:Nn \l__wheelchart_slices_tl {#1} } , slices~angle~pos /. initial = 0.5 , slices~angle~shift /. initial = 0 , slices~arc /. style~2~args = { slices~start~arc = { - (#1) } {#2} , slices~end~arc = {#1} {#2} } , slices~arc~inner~end /. is~choice , slices~arc~inner~end / false /. style = {} , slices~arc~inner~end / false /. value~forbidden , slices~arc~inner~end / true /. style = { slices~arc~match = { inner } { 1 } { -1 } { 1 } { inner~end } { inner~start } { outer~end } } , slices~arc~inner~end / true /. value~forbidden , slices~arc~inner~end /. initial = false , slices~arc~inner~end /. default = true , slices~arc~inner~end~start /. is~choice , slices~arc~inner~end~start / false /. style = {} , slices~arc~inner~end~start / false /. value~forbidden , slices~arc~inner~end~start / true /. style = { slices~arc~match = { inner } { 1 } { 1 } { 1 } { inner~end } { inner~start } { outer~end } } , slices~arc~inner~end~start / true /. value~forbidden , slices~arc~inner~end~start /. initial = false , slices~arc~inner~end~start /. default = true , slices~arc~inner~start /. is~choice , slices~arc~inner~start / false /. style = {} , slices~arc~inner~start / false /. value~forbidden , slices~arc~inner~start / true /. style = { slices~arc~match = { inner } { 1 } { -1 } { -1 } { inner~start } { inner~end } { outer~start } } , slices~arc~inner~start / true /. value~forbidden , slices~arc~inner~start /. initial = false , slices~arc~inner~start /. default = true , slices~arc~inner~start~end /. is~choice , slices~arc~inner~start~end / false /. style = {} , slices~arc~inner~start~end / false /. value~forbidden , slices~arc~inner~start~end / true /. style = { slices~arc~match = { inner } { -1 } { -1 } { -1 } { inner~start } { inner~end } { outer~start } } , slices~arc~inner~start~end / true /. value~forbidden , slices~arc~inner~start~end /. initial = false , slices~arc~inner~start~end /. default = true , slices~arc~match /. style~n~args = { 7 } { slices~end~arc = { (#2) * tan ( \__wheelchart_diff_atan:nnnn {#7} {#6} {#5} {#6} / 2 ) } { 0 } , slices~start~arc = { (#3) * tan ( \__wheelchart_diff_atan:nnnn {#7} {#6} {#5} {#6} / 2 ) } { 0 } , slices~#1~arc = { (#4) * tan ( \__wheelchart_diff_atan:nnnn {#5} {#7} {#6} {#7} / 2 ) } { 0 } } , slices~arc~outer~end /. is~choice , slices~arc~outer~end / false /. style = {} , slices~arc~outer~end / false /. value~forbidden , slices~arc~outer~end / true /. style = { slices~arc~match = { outer } { -1 } { 1 } { -1 } { outer~end } { outer~start } { inner~end } } , slices~arc~outer~end / true /. value~forbidden , slices~arc~outer~end /. initial = false , slices~arc~outer~end /. default = true , slices~arc~outer~end~start /. is~choice , slices~arc~outer~end~start / false /. style = {} , slices~arc~outer~end~start / false /. value~forbidden , slices~arc~outer~end~start / true /. style = { slices~arc~match = { outer } { -1 } { -1 } { -1 } { outer~end } { outer~start } { inner~end } } , slices~arc~outer~end~start / true /. value~forbidden , slices~arc~outer~end~start /. initial = false , slices~arc~outer~end~start /. default = true , slices~arc~outer~start /. is~choice , slices~arc~outer~start / false /. style = {} , slices~arc~outer~start / false /. value~forbidden , slices~arc~outer~start / true /. style = { slices~arc~match = { outer } { -1 } { 1 } { 1 } { outer~start } { outer~end } { inner~start } } , slices~arc~outer~start / true /. value~forbidden , slices~arc~outer~start /. initial = false , slices~arc~outer~start /. default = true , slices~arc~outer~start~end /. is~choice , slices~arc~outer~start~end / false /. style = {} , slices~arc~outer~start~end / false /. value~forbidden , slices~arc~outer~start~end / true /. style = { slices~arc~match = { outer } { 1 } { 1 } { 1 } { outer~start } { outer~end } { inner~start } } , slices~arc~outer~start~end / true /. value~forbidden , slices~arc~outer~start~end /. initial = false , slices~arc~outer~start~end /. default = true , slices~arrow /. style~2~args = { slices~start~arrow = { - (#1) } {#2} , slices~end~arrow = {#1} {#2} } , slices~end~arc /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_end_tl { \__wheelchart_slices_arc:nnnnnn {#1} {#2} { outer~end } { inner~end } { -- ( \fp_use:c { l__wheelchart_inner~end_x_fp } , \fp_use:c { l__wheelchart_inner~end_y_fp } ) } {} } } , slices~end~arrow /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_end_tl { \__wheelchart_slices_arrow:nnnnn {#1} {#2} { outer~end } { inner~end } { -- ( \fp_use:c { l__wheelchart_inner~end_x_fp } , \fp_use:c { l__wheelchart_inner~end_y_fp } ) } } } , slices~end~to /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_end_tl { \__wheelchart_slices_to:nn {#2} {#1} ( \fp_use:c { l__wheelchart_inner~end_x_fp } , \fp_use:c { l__wheelchart_inner~end_y_fp } ) } } , slices~inner~angle~reduce /. style = { slices~inner~end~angle~shift = { - (#1) } , slices~inner~start~angle~shift = {#1} } , slices~inner~angle~shift /. style = { slices~inner~end~angle~shift = {#1} , slices~inner~start~angle~shift = {#1} } , slices~inner~arc /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_inner_tl { \__wheelchart_slices_arc:nnnnnn {#1} {#2} { inner~end } { inner~start } { -- ( \fp_use:c { l__wheelchart_inner~start_x_fp } , \fp_use:c { l__wheelchart_inner~start_y_fp } ) } {} } } , slices~inner~arc~tangent /. is~choice , slices~inner~arc~tangent / false /. code = {} , slices~inner~arc~tangent / false /. value~forbidden , slices~inner~arc~tangent / true /. code = { \tl_set:Nn \l__wheelchart_slices_inner_tl { \__wheelchart_slices_arc:nnnnnn { \__wheelchart_diff_atan:nnnn { outer~start } { inner~start } { outer~end } { inner~end } } { 0 } { inner~end } { inner~start } { -- ( \fp_use:c { l__wheelchart_inner~start_x_fp } , \fp_use:c { l__wheelchart_inner~start_y_fp } ) } { \fp_compare:nNnTF { \l__wheelchart_slices_arc_A_fp } > { 359.99 } { \fp_set:Nn \l__wheelchart_slices_arc_A_fp { 1 } } { \fp_set:Nn \l__wheelchart_slices_arc_A_fp { tand ( 45 - \l__wheelchart_slices_arc_A_fp / 4 ) } } } } } , slices~inner~arc~tangent / true /. value~forbidden , slices~inner~arc~tangent /. initial = false , slices~inner~arc~tangent /. default = true , slices~inner~arrow /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_inner_tl { \__wheelchart_slices_arrow:nnnnn {#1} {#2} { inner~end } { inner~start } { -- ( \fp_use:c { l__wheelchart_inner~start_x_fp } , \fp_use:c { l__wheelchart_inner~start_y_fp } ) } } } , slices~inner~end~angle~shift /. initial = 0 , slices~inner~start~angle~shift /. initial = 0 , slices~inner~to /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_inner_tl { \__wheelchart_slices_to:nn {#2} {#1} ( \fp_use:c { l__wheelchart_inner~start_x_fp } , \fp_use:c { l__wheelchart_inner~start_y_fp } ) } } , slices~outer~angle~reduce /. style = { slices~outer~end~angle~shift = { - (#1) } , slices~outer~start~angle~shift = {#1} } , slices~outer~angle~shift /. style = { slices~outer~end~angle~shift = {#1} , slices~outer~start~angle~shift = {#1} } , slices~outer~arc /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_outer_tl { \__wheelchart_slices_arc:nnnnnn {#1} {#2} { outer~start } { outer~end } { -- ( \fp_use:c { l__wheelchart_outer~end_x_fp } , \fp_use:c { l__wheelchart_outer~end_y_fp } ) } {} } } , slices~outer~arc~tangent /. is~choice , slices~outer~arc~tangent / false /. code = {} , slices~outer~arc~tangent / false /. value~forbidden , slices~outer~arc~tangent / true /. code = { \tl_set:Nn \l__wheelchart_slices_outer_tl { \__wheelchart_slices_arc:nnnnnn { \__wheelchart_diff_atan:nnnn { outer~start } { inner~start } { outer~end } { inner~end } } { 0 } { outer~start } { outer~end } { -- ( \fp_use:c { l__wheelchart_outer~end_x_fp } , \fp_use:c { l__wheelchart_outer~end_y_fp } ) } { \fp_compare:nNnTF { \l__wheelchart_slices_arc_A_fp } > { 359.99 } { \fp_set:Nn \l__wheelchart_slices_arc_A_fp { 1 } } { \fp_compare:nNnTF { \l__wheelchart_slices_arc_A_fp } = { 180 } { \fp_set:Nn \l__wheelchart_slices_arc_A_fp { 0 } } { \fp_set:Nn \l__wheelchart_slices_arc_A_fp { cotd ( 45 - \l__wheelchart_slices_arc_A_fp / 4 ) } } } } } } , slices~outer~arc~tangent / true /. value~forbidden , slices~outer~arc~tangent /. initial = false , slices~outer~arc~tangent /. default = true , slices~outer~arrow /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_outer_tl { \__wheelchart_slices_arrow:nnnnn {#1} {#2} { outer~start } { outer~end } { -- ( \fp_use:c { l__wheelchart_outer~end_x_fp } , \fp_use:c { l__wheelchart_outer~end_y_fp } ) } } } , slices~outer~end~angle~shift /. initial = 0 , slices~outer~start~angle~shift /. initial = 0 , slices~outer~to /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_outer_tl { \__wheelchart_slices_to:nn {#1} {#2} ( \fp_use:c { l__wheelchart_outer~end_x_fp } , \fp_use:c { l__wheelchart_outer~end_y_fp } ) } } , slices~pos /. initial = 0.5 , slices~scope /. style = { slices_scope /. style = {#1} } , slices_scope /. style = {} , slices~sep /. initial = 0 , slices~start~arc /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_start_tl { \__wheelchart_slices_arc:nnnnnn {#1} {#2} { inner~start } { outer~start } { -- cycle } {} } } , slices~start~arrow/.code~2~args = { \tl_set:Nn \l__wheelchart_slices_start_tl { \__wheelchart_slices_arrow:nnnnn {#1} {#2} { inner~start } { outer~start } { -- cycle } } } , slices~start~to /. code~2~args = { \tl_set:Nn \l__wheelchart_slices_start_tl { \__wheelchart_slices_to:nn {#1} {#2} cycle } } , slices~style /. style = { slices_style /. style = {#1} } , slices_style /. style = {} , slices~style = { \WCvarB } , slices~to /. style~2~args = { slices~end~to = {#1} {#2} , slices~start~to = { - (#1) } { - (#2) } } , start~angle /. initial = 90 , start~half /. style = { start~angle = { (#1) - \fp_eval:n { \l__wheelchart_counter_or_clockwise_fp * \fp_use:c { l__wheelchart_value_1_fp } * 0.5 * ( \l__wheelchart_total_angle_fp / \WCtotalnum ) } } } , start~half /. default = 90 , title /. initial= {} , title~left /. initial = {} , title~left~sep /. initial = 0.5 , title~left~style /. style = { title~left_style /. style = {#1} } , title~left_style /. style = {} , title~sep /. initial = 0.5 , title~style /. style = { title_style /. style = {#1} } , title_style /. style = {} , total~angle /. initial = 360 , total~count /. code = { \tl_set:Nn \l__wheelchart_type_tl { totalcount } \__wheelchart_def_macro:Nn \l__wheelchart_total_count_fp {#1} } , triangle~proportional~area /. style~2~args = { domain /. expanded = 0 \c_colon_str 1 , plot = { { (##2) * sqrt ( 1 - (##1) ) * (#1) / 2 } , { - sqrt ( 1 - (##1) ) * (#2) } } , radius = { -1 } { 1 } , samples = 2 , wheel~data~pos = 0.5 } , triangle~proportional~height /. style~2~args = { domain /. expanded = 0 \c_colon_str 1 , plot = { { (##2) * ( 1 - (##1) ) * (#1) / 2 } , { ( (##1) - 1 ) * (#2) } } , radius = { -1 } { 1 } , samples = 2 , wheel~data~pos = 0.5 } , value /. initial = { \WCvarA } , WC_list /. code~2~args = { \cs_set:cpn {#1} { \use:e { \clist_item:nn {#2} { \int_mod:nn { \WCcount-1 } { \clist_count:n {#2} } + 1 } } } %note the \use:e such that \WClist also works when given as an argument to pgfmath %if the list contains a macro, for example %\begin{tikzpicture} %\def\n{1} %\wheelchart[ % value=\WClistA, % WClistA={\n} %]{\exampleforthismanual} %\end{tikzpicture} %https://tex.stackexchange.com/questions/671298/clist-item-and-pgfmathsetmacro-causing-an-error } , wheel~data /. initial = {} , wheel~data~angle~pos /. initial = 0.5 , wheel~data~angle~shift /. initial = 0 , wheel~data~pos /. initial = 0.66 , wheel~data~sep /. initial = 0 , wheel~data~style /. style = { wheel_data_style /. style = {#1} } , wheel_data_style /. style = {} , wheel~lines /. style = { bool_set_true = \l__wheelchart_wheel_lines_bool , wheel_lines /. style = {#1} } , wheel_lines /. style = {} , xbar /. style~2~args = { domain /. expanded = 0 \c_colon_str {#1} , plot = { {##1} , {##2} } , radius = { 0 } {#2} , samples = 2 , wheel~data~pos = 0.5 } , ybar /. style~2~args = { domain /. expanded = 0 \c_colon_str {#2} , plot = { {##2} , {##1} } , radius = { 0 } {#1} , samples = 2 , wheel~data~pos = 0.5 } , } \pgfkeys { / wheelchart /. unknown /. code = { \tl_set:Ne \l__wheelchart_key_name_tl { \pgfkeyscurrentname }%it is necessary to define \l__wheelchart_key_name_tl %because \pgfkeyscurrentname will be overwritten by / errors / unknown~key /. expanded \regex_match:nVTF { \{(.+)\} } \l__wheelchart_key_name_tl { \tl_set:Ne \l__wheelchart_key_range_tl { \pgfkeyscurrentname } \regex_replace_all:nnN { \{(.+)\} } {} \l__wheelchart_key_name_tl \regex_replace_all:nnN { [\w\s]+\{(.+)\} } { \1 } \l__wheelchart_key_range_tl \str_if_eq:eeTF { \l__wheelchart_key_range_tl } { list } { \pgfkeys { / wheelchart , WC_list = { l__wheelchart_list_\l__wheelchart_key_name_tl } {#1} } \pgfkeys { / wheelchart , \l__wheelchart_key_name_tl /. expand~once = { \cs:w l__wheelchart_list_\l__wheelchart_key_name_tl\cs_end: } } } { \clist_gclear:N \g__wheelchart_slice_range_for_loop_clist \foreach \l__wheelchart_slice_range_index_int [ parse = true ] in \l__wheelchart_key_range_tl { \clist_gput_right:Ne \g__wheelchart_slice_range_for_loop_clist { \fp_eval:n { \l__wheelchart_slice_range_index_int } } } \clist_map_inline:Nn \g__wheelchart_slice_range_for_loop_clist { \clist_put_right:Nn \l__wheelchart_slice_range_local_clist {##1} \clist_if_exist:cF { l__wheelchart_slice_##1_keys_clist } { \clist_new:c { l__wheelchart_slice_##1_keys_clist } } \str_if_eq:eeTF { \l__wheelchart_key_name_tl } { slice } { \clist_put_right:cn { l__wheelchart_slice_##1_keys_clist } {#1} } { \clist_put_right:ce { l__wheelchart_slice_##1_keys_clist } { \exp_not:V \l__wheelchart_key_name_tl \exp_not:n { = {#1} } } } } } } { \str_if_eq:eeTF { \str_range:Nnn \l__wheelchart_key_name_tl { 1 } { 6 } } { WClist } { \pgfkeys { / wheelchart , WC_list = { \l__wheelchart_key_name_tl } {#1} } } { \pgfkeys { / errors / unknown~key /. expanded = { \l__wheelchart_key_name_tl } {#1} } } } } }%this gives an error message if a key of the form {} is given %%> \subsection{The command \textbackslash wheelchart} \NewDocumentCommand { \wheelchart } { O{} m } { {%note the double {{...}} such that the contents is in a group and such that & can be used in pgfmath in a tabular \pgfkeys { / wheelchart , #1 } \@ifpackageloaded { siunitx } { \cs_set:Npn \WCperc { \qty { \WCpercentagerounded } { \percent } } } { \cs_set:Npn \WCperc { \WCpercentagerounded \, \% } }%the definition of \WCperc is placed inside the command \wheelchart %such that \WCperc is not defined outside this command \bool_if:NTF \l__wheelchart_legend_only_bool { \__wheelchart_initial:n {#2} \bool_if:NT \l__wheelchart_legend_row_bool { \__wheelchart_def_WClegend: } \pgfkeysvalueof { / wheelchart / legend } } { \fp_set:Nn \l__wheelchart_coord_determinant_fp { \pgf@yy * \pgf@xx - \pgf@yx * \pgf@xy } \begin { scope } [ shift /. expanded = { \pgfkeysvalueof { / wheelchart / at } } ] \begin { scope } [ local~bounding~box /. expanded = \g__wheelchart_name_tl ] \__wheelchart_def_macros:n { total~angle } \__wheelchart_initial:n {#2} \__wheelchart_def_macros:n { start~angle } \bool_if:NF \l__wheelchart_plot_bool { \bool_set_false:N \l__wheelchart_def_inner_contour_bool \bool_if:NTF \l__wheelchart_contour_bool { \bool_set_true:N \l__wheelchart_def_inner_contour_bool \tl_build_gbegin:N \g__wheelchart_outer_contour_tl \__wheelchart_for_loop:n { \tl_build_gput_left:Ne \g__wheelchart_outer_contour_tl { ( \fp_use:N \g__wheelchart_new_angle_fp \c_colon_str \fp_use:N \l__wheelchart_outer_radius_fp ) arc [ start~angle = \fp_use:N \g__wheelchart_new_angle_fp , end~angle = \fp_use:N \g__wheelchart_angle_fp , radius = \fp_use:N \l__wheelchart_outer_radius_fp ] -- } } \tl_build_gend:N \g__wheelchart_outer_contour_tl } { \bool_if:NT \l__wheelchart_middle_fill_bool { \bool_set_true:N \l__wheelchart_def_inner_contour_bool } } \bool_if:NT \l__wheelchart_def_inner_contour_bool { \tl_build_gbegin:N \g__wheelchart_inner_contour_tl \__wheelchart_for_loop:n { \tl_build_gput_right:Ne \g__wheelchart_inner_contour_tl { ( \fp_use:N \g__wheelchart_angle_fp \c_colon_str \fp_use:N \l__wheelchart_inner_radius_fp ) arc [ start~angle = \fp_use:N \g__wheelchart_angle_fp , end~angle = \fp_use:N \g__wheelchart_new_angle_fp , radius = \fp_use:N \l__wheelchart_inner_radius_fp ] -- } } \tl_build_gend:N \g__wheelchart_inner_contour_tl } \bool_if:NT \l__wheelchart_middle_fill_bool { \fill [ / wheelchart / middle_fill ] \fp_compare:nNnF { \l__wheelchart_total_angle_fp } = { 360 } { ( 0 , 0 ) -- } \g__wheelchart_inner_contour_tl cycle ; } } \bool_if:NTF \l__wheelchart_discrete_bool { \__wheelchart_discrete_algorithm: } { \__wheelchart_for_loop:n { \int_compare:nNnT { \WCcount } = { 1 } { %determine the orientation, this is necessary even if no plot is used, for example if %inner radius > outer radius then \g__wheelchart_slices_orientation_fp is different from %\l__wheelchart_counter_or_clockwise_fp \fp_set:Nn \l__wheelchart_slices_orientation_new_angle_fp { \g__wheelchart_angle_fp + ( \g__wheelchart_new_angle_fp == \g__wheelchart_angle_fp ? \l__wheelchart_counter_or_clockwise_fp * \l__wheelchart_total_angle_fp : \g__wheelchart_new_angle_fp - \g__wheelchart_angle_fp ) / \l__wheelchart_samples_fp } \path let \p { l__wheelchart_slices_orientation_1 } = ( \__wheelchart_outer_plot:nn { \fp_use:N \g__wheelchart_angle_fp } { \fp_use:N \l__wheelchart_outer_radius_fp } ) , \p { l__wheelchart_slices_orientation_2 } = ( \__wheelchart_outer_plot:nn { \fp_use:N \l__wheelchart_slices_orientation_new_angle_fp } { \fp_use:N \l__wheelchart_outer_radius_fp } ) , \p { l__wheelchart_slices_orientation_3 } = ( \__wheelchart_inner_plot:nn { \fp_use:N \l__wheelchart_slices_orientation_new_angle_fp } { \fp_use:N \l__wheelchart_inner_radius_fp } ) , \p { l__wheelchart_slices_orientation_4 } = ( \__wheelchart_inner_plot:nn { \fp_use:N \g__wheelchart_angle_fp } { \fp_use:N \l__wheelchart_inner_radius_fp } ) in [ / utils / exec = { \fp_gset:Nn \g__wheelchart_slices_orientation_fp { sign ( 0.1 * \y { l__wheelchart_slices_orientation_1 } * ( \x { l__wheelchart_slices_orientation_4 } - \x { l__wheelchart_slices_orientation_2 } ) + 0.1 * \y { l__wheelchart_slices_orientation_2 } * ( \x { l__wheelchart_slices_orientation_1 } - \x { l__wheelchart_slices_orientation_3 } ) + 0.1 * \y { l__wheelchart_slices_orientation_3 } * ( \x { l__wheelchart_slices_orientation_2 } - \x { l__wheelchart_slices_orientation_4 } ) + 0.1 * \y { l__wheelchart_slices_orientation_4 } * ( \x { l__wheelchart_slices_orientation_3 } - \x { l__wheelchart_slices_orientation_1 } ) ) * sign ( \l__wheelchart_coord_determinant_fp ) } } ] ;%the terms are multiplied with 0.1 to try to avoid an overflow \fp_compare:nNnT { \g__wheelchart_slices_orientation_fp } = { 0 } { \fp_gset_eq:NN \g__wheelchart_slices_orientation_fp \l__wheelchart_counter_or_clockwise_fp } } \pgfkeysvalueof { / wheelchart / before~slices } \bool_if:NTF \l__wheelchart_slices_bool { \__wheelchart_def_macros:n { slices~angle~pos , slices~angle~shift , slices~pos , slices~sep } \__wheelchart_def_angle:nnnN { \l__wheelchart_slices_angle_pos_fp } { \l__wheelchart_slices_angle_shift_fp } { \l__wheelchart_slices_sep_fp } \l__wheelchart_slices_angle_fp \begin { scope } [ shift /. expanded = { \__wheelchart_convex_comb_coord:nnnn { \l__wheelchart_slices_angle_pos_fp } { \l__wheelchart_slices_angle_shift_fp } { \l__wheelchart_slices_pos_fp } { \l__wheelchart_slices_sep_fp } } , rotate = \l__wheelchart_slices_angle_fp ] \fill [ / wheelchart / slices_style ] \l__wheelchart_slices_tl \end { scope } } { %Below we define x and y coordinates of the 4 points of the slice. %We do not use the let operation in the path \fill[/wheelchart/slices_style] ... because then %\n, \p, \x and \y can not be used as macro names inside the argument of a key which is applied %on this path such as the key slices inner arc. %First it is necessary to define \g__wheelchart_x_coord_fp and \g__wheelchart_y_coord_fp globally. Then we %define local macros taking these values with an expanded definition. These are defined locally such that %these macros do not interfere with values of another wheelchart, for example if wheelcharts would be nested. %We do not use a \coordinate definition because this would be global which is not suited as explained above. \__wheelchart_def_coord:nn { inner } { end } \__wheelchart_def_coord:nn { inner } { start } \__wheelchart_def_coord:nn { outer } { end } \__wheelchart_def_coord:nn { outer } { start } \fill [ / wheelchart / slices_style ] ( \fp_use:c { l__wheelchart_outer~start_x_fp } , \fp_use:c { l__wheelchart_outer~start_y_fp } ) \l__wheelchart_slices_outer_tl \l__wheelchart_slices_end_tl \l__wheelchart_slices_inner_tl \l__wheelchart_slices_start_tl ; } \pgfkeysvalueof { / wheelchart / after~slices } } } \__wheelchart_for_loop:n { \bool_if:NT \l__wheelchart_wheel_lines_bool %this is placed inside \__wheelchart_for_loop:n such that wheel lines can be applied for specific slices { \int_step_inline:nnn { 0 } { \fp_eval:n { round ( \l__wheelchart_value_fp ) } } %note the \fp_eval:n { round ( ... ) } to avoid the messages Missing character: There is no ... in font nullfont! { \fp_set:Nn \l__wheelchart_angle_wheel_lines_fp { \g__wheelchart_angle_fp + ( \l__wheelchart_counter_or_clockwise_fp * (####1) * ( \l__wheelchart_total_angle_fp / \WCtotalnum ) ) } \draw [ / wheelchart / wheel_lines ] ( \__wheelchart_inner_plot:nn { \fp_use:N \l__wheelchart_angle_wheel_lines_fp } { \fp_use:N \l__wheelchart_inner_radius_fp } ) -- ( \__wheelchart_outer_plot:nn { \fp_use:N \l__wheelchart_angle_wheel_lines_fp } { \fp_use:N \l__wheelchart_outer_radius_fp } ) ; } } } \bool_if:NF \l__wheelchart_plot_bool { \bool_if:NT \l__wheelchart_contour_bool { \fp_compare:nNnTF { \l__wheelchart_total_angle_fp } = { 360 } { \draw [ / wheelchart / contour_style ] \g__wheelchart_inner_contour_tl cycle ; \draw [ / wheelchart / contour_style ] \g__wheelchart_outer_contour_tl cycle ; } { \draw [ / wheelchart / contour_style ] \g__wheelchart_inner_contour_tl \g__wheelchart_outer_contour_tl cycle ; } } } \__wheelchart_for_loop:n { \__wheelchart_def_macros:n { data~pos , lines , lines~angle~pos , lines~angle~shift , lines~ext , lines~pos , lines~sep } \fp_compare:nNnF { \l__wheelchart_lines_ext_fp } = { 0 } { \bool_if:NF \l__wheelchart_lines_ext_dir_bool { \__wheelchart_def_macros:n { lines~ext~dirsep } \int_set:Nn \l__wheelchart_lines_ext_dir_int { \fp_eval:n { ( \WCdataangle < 90 - \l__wheelchart_lines_ext_dirsep_fp ? 1 : ( \WCdataangle <= 90 + \l__wheelchart_lines_ext_dirsep_fp ? \l__wheelchart_lines_ext_top_dir_int : ( \WCdataangle < 270 - \l__wheelchart_lines_ext_dirsep_fp ? -1 : ( \WCdataangle <= 270 + \l__wheelchart_lines_ext_dirsep_fp ? \l__wheelchart_lines_ext_bottom_dir_int : 1 ) ) ) ) } } } \__wheelchart_def_macros:n { lines~ext~fixed~left , lines~ext~fixed~right } } \fp_compare:nF { \l__wheelchart_lines_fp == 0 && \l__wheelchart_lines_ext_fp == 0 } { \draw [ / wheelchart / lines_style ] let \p { l__wheelchart_lines_1 } = \__wheelchart_convex_comb_coord:nnnn { \l__wheelchart_data_angle_pos_fp } { \l__wheelchart_data_angle_shift_fp } { \l__wheelchart_data_pos_fp } { \l__wheelchart_lines_sep_fp + \l__wheelchart_lines_fp } in \__wheelchart_convex_comb_coord:nnnn { \l__wheelchart_lines_angle_pos_fp } { \l__wheelchart_lines_angle_shift_fp } { \l__wheelchart_lines_pos_fp } { \l__wheelchart_lines_sep_fp } -- ( \p { l__wheelchart_lines_1 } ) \fp_compare:nNnF { \l__wheelchart_lines_ext_fp } = { 0 } { \str_case:enF { \pgfkeysvalueof { / wheelchart / lines~ext~fixed } } { { true } { -- ( { \fp_eval:n { \l__wheelchart_lines_ext_dir_int == 1 ? \l__wheelchart_lines_ext_fixed_right_fp : \l__wheelchart_lines_ext_fixed_left_fp } } , \y { l__wheelchart_lines_1 } ) } { false } { --++ ( { \fp_eval:n { \l__wheelchart_lines_ext_dir_int * \l__wheelchart_lines_ext_fp } } , 0 ) } } { \pgfkeys { / errors / boolean~expected /. expanded = { lines~ext~fixed } { \pgfkeysvalueof { / wheelchart / lines~ext~fixed } } } } coordinate [ shift = { ( { \fp_eval:n { \l__wheelchart_lines_ext_dir_int * \l__wheelchart_data_sep_fp } } , 0 ) } ] ( g__wheelchart_data_coordinate ) } ; } \__wheelchart_if_text:nn { data } { \fp_compare:nNnTF { \l__wheelchart_lines_ext_fp } = { 0 } { \__wheelchart_def_macros:n { anchor~xsep , anchor~ysep } \pgfmathparse { ( \WCdataangle == 0 ? "west" \c_colon_str ( \WCdataangle == 90 ? "south" \c_colon_str ( \WCdataangle == 180 ? "east" \c_colon_str ( \WCdataangle == 270 ? "north" \c_colon_str ( \WCdataangle <= \fp_use:N \l__wheelchart_anchor_ysep_fp ? "west" \c_colon_str ( \WCdataangle < 90 - \fp_use:N \l__wheelchart_anchor_xsep_fp ? "south~west" \c_colon_str ( \WCdataangle <= 90 + \fp_use:N \l__wheelchart_anchor_xsep_fp ? "south" \c_colon_str ( \WCdataangle < 180 - \fp_use:N \l__wheelchart_anchor_ysep_fp ? "south~east" \c_colon_str ( \WCdataangle <= 180 + \fp_use:N \l__wheelchart_anchor_ysep_fp ? "east" \c_colon_str ( \WCdataangle < 270 - \fp_use:N \l__wheelchart_anchor_xsep_fp ? "north~east" \c_colon_str ( \WCdataangle <= 270 + \fp_use:N \l__wheelchart_anchor_xsep_fp ? "north" \c_colon_str ( \WCdataangle < 360 - \fp_use:N \l__wheelchart_anchor_ysep_fp ? "north~west" \c_colon_str "west" )))))))))))) } \tl_set:Ne \l__wheelchart_data_anchor_tl { \pgfmathresult } \coordinate [ at = \__wheelchart_convex_comb_coord:nnnn { \l__wheelchart_data_angle_pos_fp } { \l__wheelchart_data_angle_shift_fp } { \l__wheelchart_data_pos_fp } { \l__wheelchart_data_sep_fp + ( \l__wheelchart_lines_fp == 0 ? 0 : \l__wheelchart_lines_sep_fp + \l__wheelchart_lines_fp ) } ] ( g__wheelchart_data_coordinate ) ; } { \pgfmathparse { \int_use:N \l__wheelchart_lines_ext_dir_int == 1 ? "right" \c_colon_str "left" } \tl_set:Ne \l__wheelchart_data_anchor_tl { \pgfkeysvalueof { / wheelchart / lines~ext~\pgfmathresult \c_space_tl anchor } } } \node [ anchor = \l__wheelchart_data_anchor_tl , align = left , / wheelchart / data_style ] at ( g__wheelchart_data_coordinate ) { \pgfkeysvalueof { / wheelchart / data } } ;%a separate \node and not at the end of the \draw with lines_style %such that the key lines style is not passed to this \node } \__wheelchart_def_macros:n { arc~data~angle~pos , arc~data~dir }%these are needed for arc data and arc \pgfinterruptpicture% \fp_gset:Nn \g__wheelchart_half_ex_over_one_cm_fp { 0.5 ex / 1 cm }% \endpgfinterruptpicture% \fp_gset:Nn \g__wheelchart_arc_data_factor_fp { 0 } \__wheelchart_if_text:nn { arc~data } { \__wheelchart_def_macros:n { arc~data~angle~shift , arc~data~pos , arc~data~sep } \hbox_set:Nn \l__wheelchart_arc_data_box { \pgfinterruptpicture { \pgfkeysvalueof { / wheelchart / arc~data } } \endpgfinterruptpicture } \fp_gset:Nn \g__wheelchart_arc_data_slice_length_fp { 1 }%this is necessary if the value is 0 \__wheelchart_convex_comb_coord_plot:nnnnnnn { overlay , decorate , decoration = { text~along~path , text = { {} { \fp_gset:Nn \g__wheelchart_arc_data_slice_length_fp { \pgfdecoratedpathlength } } } , raise = -0.5 ex , text~align = \l__wheelchart_arc_data_align_tl , / wheelchart / arc_data_style } }%get the length of the path %note the option overlay such that this does not increase the bounding box %note the {} at the start of text and the braces around \fp_gset:Nn ... such that the compilation does not stall { 0 } { 1 } { \l__wheelchart_plot_variable_fp } { 0 } { \l__wheelchart_arc_data_pos_fp } { \l__wheelchart_arc_data_sep_fp } \__wheelchart_convex_comb_coord_plot:nnnnnnn { decorate , decoration = { text~along~path , text = { { { \fp_gset:Nn \g__wheelchart_arc_data_factor_fp { \the \pgfdecoratedcompleteddistance } } } \pgfkeysvalueof { / wheelchart / arc~data } { { \fp_gset:Nn \g__wheelchart_arc_data_factor_fp { ( \the \pgfdecoratedcompleteddistance - \g__wheelchart_arc_data_factor_fp ) / \g__wheelchart_arc_data_slice_length_fp } } } } , raise = -0.5 ex , text~align = \l__wheelchart_arc_data_align_tl , / wheelchart / arc_data_style } }%note the double braces around \fp_gset:Nn ... so that for example arc data=text {\qty{5}{\percent}} is allowed %note that \def\mytext{}\path[decorate,decoration={text along path,text={\mytext}}] (0,0)--(1,1); %gives the message Missing character: There is no ... in font nullfont!, then %text={\pgfkeysvalueof { / wheelchart / arc~data }{}} can be used if the \fp_gset:Nn ... would not be present { \fp_use:c { c__wheelchart_arc_data_start_factor_\l__wheelchart_arc_data_align_tl _fp } } { \fp_use:c { c__wheelchart_arc_data_end_factor_\l__wheelchart_arc_data_align_tl _fp } } { \l__wheelchart_plot_variable_fp * \l__wheelchart_arc_data_dir_fp * 1.1 * ( \dim_to_fp:n { \box_wd:N \l__wheelchart_arc_data_box } / \g__wheelchart_arc_data_slice_length_fp ) + \l__wheelchart_arc_data_angle_pos_fp } { \l__wheelchart_arc_data_angle_shift_fp } { \l__wheelchart_arc_data_pos_fp } { \l__wheelchart_arc_data_sep_fp } \fp_compare:nNnT { \g__wheelchart_arc_data_factor_fp } < { 0 } { \PackageWarning { wheelchart } { The~arc~data~in~slice~\WCcount \c_space_tl did~(possibly)~not~fit.~ Increase~the~absolute~value~of~arc~data~dir. }%refer to \WCcount and not to \pgfkeysvalueof { / wheelchart / arc~data } %because the latter is not necessarily unique } } \bool_if:NT \l__wheelchart_arc_bool { \__wheelchart_def_macros:n { arc~pos , arc~sep } \str_case:enF { \pgfkeysvalueof { / wheelchart / arc~around~text } } { { true } { \__wheelchart_arc_around_text:nnn { first } { -1 } { 0 } \__wheelchart_arc_around_text:nnn { second } { 1 } { 1 } } { false } { \__wheelchart_convex_comb_coord_plot:nnnnnnn { draw , / wheelchart / arc_style } { 0 } { 1 } { \l__wheelchart_plot_variable_fp } { 0 } { \l__wheelchart_arc_pos_fp } { \l__wheelchart_arc_sep_fp } } } { \pgfkeys { / errors / boolean~expected /. expanded = { arc~around~text } { \pgfkeysvalueof { / wheelchart / arc~around~text } } } } } \__wheelchart_if_text:nn { inner~data } { \__wheelchart_def_macros:n { inner~data~angle~pos , inner~data~angle~shift , inner~data~pos , inner~data~sep } \node [ align = left , / wheelchart / inner_data_style ] at \__wheelchart_convex_comb_coord:nnnn { \l__wheelchart_inner_data_angle_pos_fp } { \l__wheelchart_inner_data_angle_shift_fp } { \l__wheelchart_inner_data_pos_fp } { \l__wheelchart_inner_data_sep_fp } { \pgfkeysvalueof { / wheelchart / inner~data } } ; } \__wheelchart_if_text:nn { wheel~data } { \__wheelchart_def_macros:n { wheel~data~angle~pos , wheel~data~angle~shift , wheel~data~pos , wheel~data~sep } \node [ align = left , / wheelchart / wheel_data_style ] at \__wheelchart_convex_comb_coord:nnnn { \l__wheelchart_wheel_data_angle_pos_fp } { \l__wheelchart_wheel_data_angle_shift_fp } { \l__wheelchart_wheel_data_pos_fp } { \l__wheelchart_wheel_data_sep_fp } { \pgfkeysvalueof { / wheelchart / wheel~data } } ; } \pgfkeysvalueof { / wheelchart / legend~entry } } \bool_if:NT \l__wheelchart_legend_row_bool { \__wheelchart_def_WClegend: } \__wheelchart_if_text:nn { middle } { \node [ align = center , / wheelchart / middle_style ] at ( 0 , 0 ) { \pgfkeysvalueof { / wheelchart / middle } } ; } \pgfkeysvalueof { / wheelchart / legend } \end { scope } \__wheelchart_caption_and_title:nnnnn { caption~left } { north~west } { left } { \g__wheelchart_name_tl .south~west } { -1 } \__wheelchart_caption_and_title:nnnnn { caption } { north } { center } { \g__wheelchart_name_tl .south -| 0 , 0 } { -1 } \__wheelchart_caption_and_title:nnnnn { title~left } { south~west } { left } { \g__wheelchart_name_tl .north~west } { 1 } \__wheelchart_caption_and_title:nnnnn { title } { south } { center } { \g__wheelchart_name_tl .north -| 0 , 0 } { 1 } \end { scope } } } }