使用图案填充时出现问题

使用图案填充时出现问题
\usepackage{tikz}
\usetikzlibrary{patterns, arrows}

\begin{document}
\begin{tikzpicture}
  % Set the width and height of the rectangles
  \pgfmathsetmacro{\rectHeight}{1} % Height of all rectangles
  \pgfmathsetmacro{\totalWidth}{8} % Total width of the bottom rectangle
  \pgfmathsetmacro{\toprecPercentage}{0.8} % Width of the top rectangle as a percentage of the bottom rectangle
  
  % Define the number of rectangles
  \def\numRectangles{9}
  
  % Define an array of descriptions for the arrows
  \def\descriptions{{"Desc 0", "Desc 1", "Desc 2", "Desc 3", "Desc 4", "Desc 5", "Desc 6", "Desc 7", "Desc 8"}}
  
  % Define an array of segment counts
  \def\segmentCounts{{3, 9, 1, 1, 1, 1, 1, 1, 1}} % Number of segments for each rectangle

  % Define segmentFillPercentages for each rectangle
  \def\segmentFillPercentages{
    {70, 30, 50},  % Customize these percentages for rectangle 0
    {20, 40, 60, 80, 10, 30, 50, 70, 90},  % Customize these percentages for rectangle 1
    {10},         % Customize these percentages for rectangle 2
    {40},         % Customize these percentages for rectangle 3
    {20},         % Customize these percentages for rectangle 4
    {10},         % Customize these percentages for rectangle 5
    {40},         % Customize these percentages for rectangle 6
    {20},         % Customize these percentages for rectangle 7
    {100}         % Customize these percentages for rectangle 8
  }
  
  % Calculate the width of the top rectangle
  \pgfmathsetmacro{\toprecWidth}{\toprecPercentage*\totalWidth}
  
  % Draw the rectangles and fill them with different patterns based on patterns based on fill percentages and segment counts
  \foreach \i in {0,...,\numexpr\numRectangles-1} {
    \pgfmathsetmacro{\currentWidth}{\totalWidth - (\i/\numRectangles)*\toprecWidth}
    \pgfmathsetmacro{\startingPoint}{0.5*(\totalWidth-\currentWidth)} % Calculate the starting point
    
    % Draw segments within each rectangle
    \pgfmathsetmacro{\segmentCount}{\segmentCounts[\i]}
    \pgfmathsetmacro{\segmentWidth}{\currentWidth/\segmentCount}
    
    % Get the fill percentages for the current rectangle
    \pgfmathparse{\segmentFillPercentages[\i]}
    \let\currentSegmentFillPercentages\pgfmathresult
    
    % Draw and fill each segment with different fill percentages
    \foreach \j in {1,...,\segmentCount} {
      \pgfmathparse{\currentSegmentFillPercentages[\j-1]}
      \let\segmentFillPercentage\pgfmathresult
      \pgfmathsetmacro{\segmentStartingPoint}{\startingPoint + (\j-1)*\segmentWidth}
      
      \draw (\segmentStartingPoint,\rectHeight*\i) rectangle (\segmentStartingPoint + \segmentWidth,\rectHeight*\i+\rectHeight);
      \fill[pattern=grid,pattern color=redpattern=grid,pattern color=red] (\segmentStartingPoint,\rectHeight*\i) rectangle (\segmentStartingPoint + \segmentWidth,\rectHeight*\i+(\segmentFillPercentage/100)*\rectHeight);
    }
    
    % Add arrows and descriptions within the loop
    \draw[->] (\startingPoint + \currentWidth + 0.2, \rectHeight*\i + 0.5*\rectHeight) -- (\startingPoint + \currentWidth + 1.0, \rectHeight*\i + 0.5*\rectHeight) node[right,font=\footnotesize,text width=2cm] {\pgfmathparse{\descriptions[\i]}\pgfmathresult};
  }
\end{tikzpicture}
\end{document}

尝试了不同的方法来获取片段的填充颜色,但无法获得正确的颜色。任何关于解决此问题的帮助都将不胜感激。

答案1

循环\fill\j有一个错误的选项(缺少逗号):

\fill[pattern=grid,pattern color=redpattern=grid,pattern color=red] …;

让我们修复这个问题:

\fill[pattern=grid,pattern color=red] …;

相同的路径在坐标内使用括号进行计算。您将得到保护那些来自 TikZ 解析器的人加上另一副大括号:

 (\segmentStartingPoint + \segmentWidth,
   {\rectHeight*\i+(\segmentFillPercentage/100)*\rectHeight})

不过,括号不是必需的,您可以在这里使用相对坐标:

\fill[pattern=grid,pattern color=red]
  (\segmentStartingPoint, \rectHeight*\i)
  rectangle +(\segmentWidth, \segmentFillPercentage/100*\rectHeight);

对于数组,数组\segmentFillPercentages需要另一组括号,如下所示手册指出

{x}  (数组运算符)

[…]⟨array specification⟩由逗号分隔的元素组成,例如{1, 2, 3, 4, 5}。 […] 此外,数组的元素可以是数组本身,从而允许模拟多维数组:{1, {2,3}, {4,5}, 6}。在宏中存储数组时,请不要忘记周围的括号:\def\myarray{{1,2,3}}不是\def\myarray{1,2,3}

在这里,我选择在 PGFMath 公式中插入这些括号:

\pgfmathsetmacro\currentSegmentFillPercentages{{\segmentFillPercentages}[\i]}

不幸的是,此时列表内的列表将转换为数组的内部表示,这意味着以后的访问将\currentSegmentFillPercentages不再起作用。您可以改用两个数组访问运算符:

\pgfmathsetmacro\segmentFillPercentage{{\segmentFillPercentages}[\i][\j]}

或者

\pgfmathArraysetmacro{\segmentFillPercentage}{\currentSegmentFillPercentages}{\j}

这样 PGFMath 就不需要[\i]多次访问。

但是,对于只有一个段的矩形,这两种方法都无法正常工作,因为内部表示不再兼容。

对于这一点,我们直接采用即可\currentSegmentFillPercentages

(我还将\j循环转换为 0,...,\segmentCount-1 循环。)

代码

\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns, arrows}
\makeatletter
\newcommand*\pgfmathArraysetmacro[3]{%
  \pgfmathtruncatemacro\@temp{#3}%
  \expandafter\pgfmatharray@#2{\@temp}%
  \let#1\pgfmathresult}
\makeatother
\begin{document}
\begin{tikzpicture}
% Set the width and height of the rectangles
\pgfmathsetmacro{\rectHeight}{1} % Height of all rectangles
\pgfmathsetmacro{\totalWidth}{8} % Total width of the bottom rectangle
\pgfmathsetmacro{\toprecPercentage}{0.8} % Width of the top rectangle as a percentage of the bottom rectangle

% Define the number of rectangles
\def\numRectangles{9}

% Define an array of descriptions for the arrows
\def\descriptions{{"Desc 0", "Desc 1", "Desc 2", "Desc 3", "Desc 4", "Desc 5", "Desc 6", "Desc 7", "Desc 8"}}

% Define an array of segment counts
\def\segmentCounts{{3, 9, 1, 1, 1, 1, 1, 1, 1}} % Number of segments for each rectangle

% Define segmentFillPercentages for each rectangle
\def\segmentFillPercentages{
  {70, 30, 50},  % Customize these percentages for rectangle 0
  {20, 40, 60, 80, 10, 30, 50, 70, 90},  % Customize these percentages for rectangle 1
  {10},         % Customize these percentages for rectangle 2
  {40},         % Customize these percentages for rectangle 3
  {20},         % Customize these percentages for rectangle 4
  {10},         % Customize these percentages for rectangle 5
  {40},         % Customize these percentages for rectangle 6
  {20},         % Customize these percentages for rectangle 7
  {100}         % Customize these percentages for rectangle 8
}

% Calculate the width of the top rectangle
\pgfmathsetmacro{\toprecWidth}{\toprecPercentage*\totalWidth}

% Draw the rectangles and fill them with different patterns based on patterns based on fill percentages and segment counts
\foreach \i in {0,...,\inteval{\numRectangles-1}} {
  \pgfmathsetmacro{\currentWidth}{\totalWidth - (\i/\numRectangles)*\toprecWidth}
  \pgfmathsetmacro{\startingPoint}{0.5*(\totalWidth-\currentWidth)} % Calculate the starting point
  
  % Draw segments within each rectangle
  \pgfmathsetmacro{\segmentCount}{\segmentCounts[\i]}
  \pgfmathsetmacro{\segmentWidth}{\currentWidth/\segmentCount}
  
  % Get the fill percentages for the current rectangle
  \pgfmathsetmacro\currentSegmentFillPercentages{{\segmentFillPercentages}[\i]}
  \typeout{\currentSegmentFillPercentages}
  % Draw and fill each segment with different fill percentages
  \foreach \j in {0,...,\inteval{\segmentCount-1}} {
    \ifnum\segmentCount=1 % need to check special case of just one segment
      \let\segmentFillPercentage\currentSegmentFillPercentages
    \else
      \pgfmathsetmacro\segmentFillPercentage{{\segmentFillPercentages}[\i][\j]}  % Option 1
%      \pgfmathArraysetmacro{\segmentFillPercentage}{\currentSegmentFillPercentages}{\j} % Option 2
    \fi

    \pgfmathsetmacro{\segmentStartingPoint}{\startingPoint + \j*\segmentWidth}

    \draw (\segmentStartingPoint, \rectHeight*\i) rectangle +(\segmentWidth, \rectHeight);
    \fill[pattern=grid,pattern color=red] (\segmentStartingPoint,\rectHeight*\i) rectangle + (\segmentWidth, \segmentFillPercentage/100*\rectHeight);
  }
    
  % Add arrows and descriptions within the loop
  \draw[->] (\startingPoint + \currentWidth + 0.2, \rectHeight*\i + 0.5*\rectHeight) -- +(.8,0)
    node[right, font=\footnotesize, text width=2cm] {\pgfmathprint{\descriptions[\i]}};
}
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案2

这是绘制该图的另一种方法。

您需要三个宏:

  • \botWidth描述底部矩形的宽度,
  • \topWidth描述顶部矩形的宽度和
  • \LIST包含描述列表和百分比列表。

该宏\countList用于计算的元素\LIST,我们不能——与\Percs后面不同——使用dim函数,因为\LIST它不仅包含数学。

该图的其余部分是一个大的\foreach循环,循环遍历\LIST。使用evaluate键,将评估百分比数,并从和\Width计算矩形的。(矩形的宽度实际上是指定数字的两倍。)\botWidth\topWidth

矩形的高度已设置,1但可以通过设置不同的y矢量轻松调整。

将绘制矩形并将path picture使用绘制图案:
为此设置一个坐标系,以便

  • (0, 0)位于左下角,
  • (1, 0)位于右下角,
  • (0, 1)位于左上角,
  • (1, 1)位于右上角。

(这只在不使用旋转或倾斜等变换的情况下才有效。)这意味着我们可以使用1/\numPercs图案矩形的宽度和\perc/100高度。

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta, calc, patterns}
\newcommand*\countList[2]{% not the most efficient but oh well
  \setcounter{pgf@counta}{0}%
  \foreach~in#1{\stepcounter{pgf@counta}}%
  \edef#2{\the\value{pgf@counta}}}
\begin{document}
\begin{tikzpicture}[thick]
\newcommand*\botWidth{4}
\newcommand*\topWidth{1}
\newcommand*\LIST{%
  Desc 0/{70, 30, 50},
  Desc 1/{20, 40, 60, 80, 10, 30, 50, 70, 90},
  Desc 2/{10},
  Desc 3/{40},
  Desc 4/{20},
  Desc 5/{10},
  Desc 6/{40},
  Desc 7/{20},
  Desc 8/{100}}

\countList\LIST\n
\foreach[
  count=\i from 0,
  evaluate={
    \numPercs=dim({\Percs});
    \Width=\botWidth-(\botWidth-\topWidth)/(\n-1)*\i;
  }] \Title/\Percs in \LIST {
  \draw (-\Width,\i) rectangle +(2*\Width,1) coordinate (tr) [
    path picture={
      \tikzset{shift=(path picture bounding box.south west),
                   x=(path picture bounding box.south east),
                   y=(path picture bounding box.north west)}
      \coordinate (@) at (0, 0);
      \foreach \perc in \Percs
        \path[pattern=grid, pattern color=red]
          (@) edge (@|-0,1)
          (@) rectangle +(1/\numPercs,\perc/100)
          coordinate (@) at (current path bounding box.south east);
    },
  ];
  \draw[->] ([shift=(down:.5), xshift=5mm]tr) -- +(right:8mm)
    node[right] {\Title};
}
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

相关内容