在 tikz 中对齐嵌套的甜甜圈形状的图表

在 tikz 中对齐嵌套的甜甜圈形状的图表

我正在尝试用 tikz 制作一个嵌套的环形图表,以显示最近使用 MEA 系统的研究中使用的不同细胞类型的百分比。外层分为两层:非神经元和神经元研究。我的内层按研究数量划分,包括神经元和非神经元细胞。我有以下问题:

  • 是否可以将内圈与神经元细胞百分比和外圈细胞的“神经元”部分对齐(反之亦然)。如果有一个选项可以旋转内圈,那么对齐就很容易了。
  • 我怎样才能使从内圆出发的线条从每个相应的黑点开始(就像在外圆中所做的那样)?

最后,如果您对我的图表的美观性有任何其他建议,请随时提供意见!我的代码(如下)是从此评论中分叉出来的这里

感谢您的时间。

\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{fadings}

% POR AS PERCENTAGENS COMO NO LATEX DA QUESTAO !

\pgfkeys{%
/piechartthreed/.cd,
scale/.code                =  {\def\piechartthreedscale{#1}},
mix color/.code            =  {\def\piechartthreedmixcolor{#1}},
background color/.code     =  {\def\piechartthreedbackcolor{#1}},
name/.code                 =  {\def\piechartthreedname{#1}}}

 \newcommand\piechartthreed\[2\]\[\]{% 
   \pgfkeys{/piechartthreed/.cd,
     scale            = 1,
     mix color        = gray,
     background color = white,
     name             = pc} 
  \pgfqkeys{/piechartthreed}{#1}
  \begin{scope}\[scale=\piechartthreedscale\] 
  \begin{scope}\[xscale=5,yscale=3\] 
     \path\[preaction={fill=black,opacity=.8,
         path fading=circle with fuzzy edge 20 percent,
         transform canvas={yshift=-15mm*\piechartthreedscale}}\] (0,0) circle (1cm);
    \fill\[gray\](0,0) circle (0.5cm);  
     \path\[preaction={fill=\piechartthreedbackcolor,opacity=.8,
          path fading=circle with fuzzy edge 20 percent,
          transform canvas={yshift=-10mm*\piechartthreedscale}}\] (0,0) circle (0.5cm);
     \pgfmathsetmacro\totan{0} 
     \global\let\totan\totan 
     \pgfmathsetmacro\bottoman{180} \global\let\bottoman\bottoman 
     \pgfmathsetmacro\toptoman{0}   \global\let\toptoman\toptoman 
     \begin{scope}\[draw=black,thin\]
     \foreach \an/\col \[count=\xi\] in {#2}{%
     \def\space{ } 
        \coordinate (\piechartthreedname\space\xi) at (\totan+\an/2:0.75cm); 
        \ifdim 180pt>\totan pt 
         \ifdim 0pt=\toptoman pt
            \shadedraw\[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin\] (0:.5cm) -- ++(0,-3mm) arc (0:\totan+\an:.5cm) 
                                                       -- ++(0,3mm)  arc (\totan+\an:0:.5cm);
            \pgfmathsetmacro\toptoman{180} 
            \global\let\toptoman\toptoman         
            \else
            \shadedraw\[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin\](\totan:.5cm)-- ++(0,-3mm) arc(\totan:\totan+\an:.5cm)
                                                        -- ++(0,3mm)  arc(\totan+\an:\totan:.5cm); 
          \fi
        \fi   
        \fill\[\col!20!gray,draw=black\] (\totan:0.5cm)--(\totan:1cm)  arc(\totan:\totan+\an:1cm)
                                     --(\totan+\an:0.5cm) arc(\totan+\an:\totan :0.5cm);     
       \pgfmathsetmacro\finan{\totan+\an}
       \ifdim 180pt<\finan pt 
         \ifdim 180pt=\bottoman pt5
            \shadedraw\[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin\] (180:1cm) -- ++(0,-3mm) arc (180:\totan+\an:1cm) 
                                                       -- ++(0,3mm)  arc (\totan+\an:180:1cm);
            \pgfmathsetmacro\bottoman{0}
            \global\let\bottoman\bottoman
            \else
            \shadedraw\[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin\](\totan:1cm)-- ++(0,-3mm) arc(\totan:\totan+\an:1cm)
                                                        -- ++(0,3mm)  arc(\totan+\an:\totan:1cm); 
          \fi
        \fi
        \pgfmathsetmacro\totan{\totan+\an}  \global\let\totan\totan 
       } 
    \end{scope}
    \draw\[thin,black\](0,0) circle (0.5cm);
   \end{scope}  
\end{scope}
}
\newcommand{\innerchartthreed}\[1\]{
   % Calculate total
   \pgfmathsetmacro{\totalnum}{0}
   \foreach \value/\colour/\name in {#1} {
     \pgfmathparse{\value+\totalnum}
     \global\let\totalnum=\pgfmathresult
   }


  \pgfmathsetmacro{\wheelwidth}{\outerradius-\innerradius}
  \pgfmathsetmacro{\midradius}{(\outerradius+\innerradius)/2}

  \begin{scope}\[rotate=90,xscale=0.6,yscale=1\]

    \pgfmathsetmacro{\cumnum}{0}
    \foreach \[count=\n\] \value/\colour/\name in {#1} {
        \pgfmathsetmacro{\newcumnum}{\cumnum + \value/\totalnum*360}

        \pgfmathsetmacro{\midangle}{-(\cumnum+\newcumnum)/2}

        \filldraw\[draw=black,fill=\colour\] (-\cumnum:\outerradius) arc (-\cumnum:-(\newcumnum):\outerradius) --
        (-\newcumnum:\innerradius) arc (-\newcumnum:-(\cumnum):\innerradius) -- cycle;

        \fill\[transparent\] circle (\innerradius);

        \draw node \[text=white, font=\bfseries\] (inner \n) at (\midangle:{\innerradius+\wheelwidth/2}) {\name};


        \global\let\cumnum=\newcumnum
    }


  \end{scope}

  }
\begin{document} 

\begin{tikzpicture}
%\fill (1.8,-2.1) circle (.5mm);
\end{tikzpicture}

\definecolor{ao(english)}{rgb}{0.0, 0.5, 0.0}
\definecolor{azure(colorwheel)}{rgb}{0.0, 0.5, 1.0}
\definecolor{cardinal}{rgb}{0.77, 0.12, 0.23}
\definecolor{caribbeangreen}{rgb}{0.0, 0.8, 0.6}
\definecolor{carolinablue}{rgb}{0.6, 0.73, 0.89}


\begin{tikzpicture}
%\fill (0,0) circle (.5mm);
\piechartthreed\[scale=0.8,
                   background color=orange!50,
                   mix color=darkgray\]
                   {261/red,99/green}

\foreach \i in {1,...,2} { \fill (pc \i) circle (.8mm);}

\draw\[darkgray\] (pc 1)  -- ++(-2.95,0.5) coordinate (s1) node\[anchor=south east\] {\Large{\textbf{Non-neuronal}}}
                                                    node\[anchor=north east\] {\Large{72.3\%}};

\draw\[darkgray\] (pc 2)  -- (5.5,-2) coordinate(s2) node\[anchor=south west\] {\Large{\textbf{Neuronal}}} 
                                 node\[anchor=north west\] {\Large{45.5\%}}; 
%
%\draw\[darkgray\] (pc 3)  -- ++(3,-1) coordinate (s3) node\[anchor=south west\] {Sector 3}
%%                                                    node\[anchor=north west\] {14\%};
%%
%\draw\[darkgray\] (pc 4)  -- ++(3,0) coordinate (s4) node\[anchor=south west\] {Sector 4}
%%                                                   node\[anchor=north west\] {25\%};
%%
%\draw\[darkgray\] (pc 2)  -- ++(3,-2) coordinate (s2) -- (s2 -| s4) node\[anchor=south west\] {Sector 5}                                                                  node\[anchor=north west\] {17\%}; 

\def\innerradius{0.7cm}
\def\outerradius{1.75cm}
\pgfmathsetlengthmacro{\centerradius}{(\outerradius + \innerradius)/2}
\pgfmathsetlengthmacro{\donutcenter}{\innerradius/2}

% Clock-wise order, with cardiomyocyte: 

%Non-neuronal (cardinal): cardiomyocite, fibroblast, hek-293, sh-sy5y,rbl-1
%Neuronal (green): cortex, hippocampus, ventricular, drg
\innerchartthreed{95/cardinal!95/,38/cardinal!60/,38/cardinal!50/,38/cardinal!40/,19/cardinal!40/,56/green!90/,38/green!70/,19/green!50/,19/green!50/}

    \fill (inner 1) circle (.5mm);
  \draw\[darkgray\] (inner 1.center)  -- (4.2,1) node\[anchor=south west\] {Cardiomyocyte};

  \fill (inner 2) circle (.5mm);
  \draw\[darkgray\] (inner 2.center)  -- (4.5,-.5) node\[anchor=west\] {Fibroblast};

    \fill (inner 3) circle (.5mm);
    \draw\[darkgray\] (inner 3.center)  -- (3.5,-3) node\[anchor=west\] {HEK-293};

    \fill (inner 4) circle (.5mm);
    \draw\[darkgray\] (inner 4.center)  -- (2,-3.9) node\[anchor=north\] {SH-SY5Y};

    \fill (inner 4) circle (.5mm);
    \draw\[darkgray\] (inner 4.center)  -- (2,-3.9) node\[anchor=north\] {SH-SY5Y};

    \fill (inner 5) circle (.5mm);
    \draw\[darkgray\] (inner 5.center)  -- (-1,-4.2) node\[anchor=north\] {RBL-1};

    \fill (inner 6) circle (.5mm);
    \draw\[darkgray\] (inner 6.center)  -- (-3.5,-3.9) node\[anchor=north\] {Cortex};

    \fill (inner 7) circle (.5mm);
    \draw\[darkgray\] (inner 7.center)  -- (-6.5,-0.6) node\[anchor=north\] {Hippocampus};

    \fill (inner 8) circle (.5mm);
    \draw\[darkgray\] (inner 8.center)  -- (-1.85,3.2) node\[anchor=south east\] {Ventricular};

    \fill (inner 9) circle (.5mm);
    \draw\[darkgray\] (inner 9.center)  -- (0,3.2) node\[anchor=south west\] {DRG};

\end{tikzpicture}

\end{document}


%     TO-DO: 

%Addendum: I also wanted the colors a bit more shiny. I was able to achieve this by adding pgfkeys for mix rate low and mix rate high and replace the values 20/5 in the code with \piechartthreedmixratehigh/\piechartthreedmixratelow. Then setting the high/low mix rates to 80/60 makes nice and shiny colors. You also need to replace the remaining occurence of gray in \col!20!gray with \piechartthreedmixcolor][2]][2]

[这是我提供的代码编译后的 .pdf 的样子][3]

最后编辑:如果有人感兴趣的话,这是我的最终图像:

答案1

我认为你正在寻找这样的东西:

在此处输入图片描述

为了实现这一点,我修改了\innerchartthreed宏,现在它采用逗号分隔的四元组列表:数量、颜色、名称、偏移量。OP 中的数量加起来为 360,但实际上,代码会将适当的角度计​​算为这些数量总和的百分比,因此您可以使用原始数据来指定数量。

接下来,我更改了\innerchartthreed宏,使其将名称添加到圆圈外部,并在每个段内添加一条线来标记。由于图片中的圆圈实际上是椭圆形,我看不出有什么简单的方法可以自动设置名称与中心的距离,因为与图表中心的距离会随着角度而变化,因此我添加了偏移量以将标签沿径向线进一步向外移动。此外,我添加了一个可选参数来\innerchartthreed设置内圆相对于外圆盘的起始角度。这允许您调整内圆以匹配外圆(奇怪的是,调整应该是 228,但我发现 222 看起来更好)。

最终结果是,带有标签的内盘由以下方式绘制:

  \innerchartthreed[222]{% amount/colour/name/label offset
      95/cardinal!95/Cardiomyocyte/1.2,
      38/cardinal!60/Fibroblast/0.2,
      38/cardinal!50/HEK-293/0,
      38/cardinal!40/SH-SY5Y/0.5,
      19/cardinal!40/RBL-1/0.5,
      56/green!90/Cortex/1,
      38/green!70/Hippocampus/1.8,
      19/green!50/Ventricular/1.8,
      19/green!50/DRG/1.5
    }

之后,我又做了一些类似的调整,以便 \piechartthreed放置外圆标签。带标签的外圆盘不是由以下人员绘制的:

  % amount/color/name
  \piechartthreed[scale=0.8, background color=orange!50, mix color=darkgray]{
      228/red/Non-neuronal\\72.3\%,
      132/green/Neuronal\\45.5\%
  }

当然,我只是破解了问题中的代码,正如 OP 所说,大部分艰苦的工作都是由 Alain Matthes 在他的精彩回答中完成的如何使用 pgf-plot 设计 3D 甜甜圈饼图?

哦,楼主SH-SY5输入了两次标签,所以我删除了一个。不确定 72.3% 和 45.5%,但我没有更改这个。

以下是更新后的代码:

\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{fadings}

\pgfkeys{%
  /piechartthreed/.cd,
  scale/.code                =  {\def\piechartthreedscale{#1}},
  mix color/.code            =  {\def\piechartthreedmixcolor{#1}},
  background color/.code     =  {\def\piechartthreedbackcolor{#1}},
  name/.code                 =  {\def\piechartthreedname{#1}}
}

 \newcommand\piechartthreed[2][]{%
   \pgfkeys{/piechartthreed/.cd,
     scale            = 1,
     mix color        = gray,
     background color = white,
     name             = pc}
  \pgfqkeys{/piechartthreed}{#1}
  \begin{scope}[scale=\piechartthreedscale]
  \begin{scope}[xscale=5,yscale=3]
     \path[preaction={fill=black,opacity=.8,
         path fading=circle with fuzzy edge 20 percent,
         transform canvas={yshift=-15mm*\piechartthreedscale}}] (0,0) circle (1cm);
    \fill[gray](0,0) circle (0.5cm);
     \path[preaction={fill=\piechartthreedbackcolor,opacity=.8,
          path fading=circle with fuzzy edge 20 percent,
          transform canvas={yshift=-10mm*\piechartthreedscale}}] (0,0) circle (0.5cm);
     \pgfmathsetmacro\totan{0}
     \global\let\totan\totan
     \pgfmathsetmacro\bottoman{180} \global\let\bottoman\bottoman
     \pgfmathsetmacro\toptoman{0}   \global\let\toptoman\toptoman
     \begin{scope}[draw=black,thin]
     \foreach \an/\col/\name [count=\xi] in {#2}{%
        \ifdim 180pt>\totan pt
         \ifdim 0pt=\toptoman pt
            \shadedraw[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin] (0:.5cm) -- ++(0,-3mm) arc (0:\totan+\an:.5cm)
                                                       -- ++(0,3mm)  arc (\totan+\an:0:.5cm);
            \pgfmathsetmacro\toptoman{180}
            \global\let\toptoman\toptoman
            \else
            \shadedraw[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin](\totan:.5cm)-- ++(0,-3mm) arc(\totan:\totan+\an:.5cm)
                                                        -- ++(0,3mm)  arc(\totan+\an:\totan:.5cm);
          \fi
        \fi
        \fill[\col!20!gray,draw=black] (\totan:0.5cm)--(\totan:1cm)  arc(\totan:\totan+\an:1cm)
                                     --(\totan+\an:0.5cm) arc(\totan+\an:\totan :0.5cm);
       \pgfmathsetmacro\finan{\totan+\an}
       \ifdim 180pt<\finan pt
         \ifdim 180pt=\bottoman pt5
            \shadedraw[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin] (180:1cm) -- ++(0,-3mm) arc (180:\totan+\an:1cm)
                                                       -- ++(0,3mm)  arc (\totan+\an:180:1cm);
            \pgfmathsetmacro\bottoman{0}
            \global\let\bottoman\bottoman
            \else
            \shadedraw[left color=\col!20!\piechartthreedmixcolor,
                       right color=\col!5!\piechartthreedmixcolor,
                       draw=black,very thin](\totan:1cm)-- ++(0,-3mm) arc(\totan:\totan+\an:1cm)
                                                        -- ++(0,3mm)  arc(\totan+\an:\totan:1cm);
          \fi
        \fi
        \node (\piechartthreedname\xi) at (\totan+2*\an/3:0.75cm){$\bullet$};
        \node[align=center] (\piechartthreedname label\xi) at (\totan+2*\an/3:1.75cm) {\Large\name};
        \draw[darkgray](\piechartthreedname\xi.center)--(\piechartthreedname label\xi);
        \pgfmathsetmacro\totan{\totan+\an}  \global\let\totan\totan
       }
    \end{scope}
    \draw[thin,black](0,0) circle (0.5cm);
   \end{scope}
\end{scope}
}
\newcommand{\innerchartthreed}[2][0]{
   % Calculate total
   \pgfmathsetmacro{\totalnum}{0}
   \foreach \value/\colour/\name/\offset in {#2} {
     \pgfmathparse{\value+\totalnum}
     \global\let\totalnum=\pgfmathresult
   }

  \pgfmathsetmacro{\wheelwidth}{\outerradius-\innerradius}
  \pgfmathsetmacro{\midradius}{(\outerradius+\innerradius)/2}

  \begin{scope}[rotate=90,xscale=0.6,yscale=1]
    \pgfmathsetmacro{\cumnum}{#1}
    \foreach [count=\n] \value/\colour/\name/\offset in {#2} {
        \pgfmathsetmacro{\newcumnum}{\cumnum + \value/\totalnum*360}

        \pgfmathsetmacro{\midangle}{Mod(-(\cumnum+\newcumnum)/2, 360)}

        \filldraw[draw=black,fill=\colour] (-\cumnum:\outerradius) arc (-\cumnum:-(\newcumnum):\outerradius) --
        (-\newcumnum:\innerradius) arc (-\newcumnum:-(\cumnum):\innerradius) -- cycle;

        \draw node [text=black, font=\bfseries] (inner \n) at (\midangle:{\innerradius+\wheelwidth/2}) {$\bullet$};
        \node (inner label \n) at (\midangle:{5+\offset}) {\name};
        \draw[darkgray] (inner \n.center)  -- (inner label \n);

        \global\let\cumnum=\newcumnum
    }
    \fill[transparent] circle (\innerradius);
  \end{scope}
  }
\begin{document}

\definecolor{ao(english)}{rgb}{0.0, 0.5, 0.0}
\definecolor{azure(colorwheel)}{rgb}{0.0, 0.5, 1.0}
\definecolor{cardinal}{rgb}{0.77, 0.12, 0.23}
\definecolor{caribbeangreen}{rgb}{0.0, 0.8, 0.6}
\definecolor{carolinablue}{rgb}{0.6, 0.73, 0.89}

\def\innerradius{0.7cm}
\def\outerradius{1.75cm}
\pgfmathsetlengthmacro{\centerradius}{(\outerradius + \innerradius)/2}
\pgfmathsetlengthmacro{\donutcenter}{\innerradius/2}

\begin{tikzpicture}

  % amount/color/name
  \piechartthreed[scale=0.8, background color=orange!50, mix color=darkgray]{
      228/red/Non-neuronal\\72.3\%,
      132/green/Neuronal\\45.5\%
  }

  % Clock-wise order, with cardiomyocyte:
  % Non-neuronal (cardinal): cardiomyocite, fibroblast, hek-293, sh-sy5y,rbl-1
  % Neuronal (green): cortex, hippocampus, ventricular, drg

  % amount/colour/name/label offset
  \innerchartthreed[222]{
      95/cardinal!95/Cardiomyocyte/1.2,
      38/cardinal!60/Fibroblast/0.2,
      38/cardinal!50/HEK-293/0,
      38/cardinal!40/SH-SY5Y/0.5,
      19/cardinal!40/RBL-1/0.5,
      56/green!90/Cortex/1,
      38/green!70/Hippocampus/1.8,
      19/green!50/Ventricular/1.8,
      19/green!50/DRG/1.5
    }
\end{tikzpicture}

\end{document}

相关内容