正确对齐 tikz 生成的金字塔图中的梯形

正确对齐 tikz 生成的金字塔图中的梯形

我正在尝试使用 tikz 创建如下所示的金字塔图表: 根据需要绘制金字塔图

因此,我进行了一些研究并发现了这个线索:tikz 制作的 3D 金字塔图

以上面的线程中的示例为例,我对其进行了调整以满足我的需求,最终得到了以下代码:

\usepackage{tikz,pgfplots}
\usetikzlibrary{shapes.geometric}

\begin{tikzpicture}[
        3d trapezium angle/.code={
            \def\threedtrapeziumangle{#1}
        },
        3d trapezium angle=60,
        3d trapezium/.style={
            shape=trapezium,
            trapezium angle=\threedtrapeziumangle,
            trapezium stretches body=true,
            line width=0pt,
            inner xsep=0pt,
            fill=#1!75!black,
            text=white,
            font=\bfseries,
            text height=.8em,
            text depth=.2em,
            append after command={
                \pgfextra{ 
                    \fill[#1!50!black] (\tikzlastnode.bottom left corner) --     
                    (\tikzlastnode.bottom right corner) -- 
                    ([shift={(-.1,-.33)}]\tikzlastnode.bottom right corner) -- 
                    ([shift={(.1,-.33)}]\tikzlastnode.bottom left corner) --
                    cycle;
                }
            }
        },
        triangle cap/.append style={
            append after command={
                \pgfextra{ 
                    \path (\tikzlastnode.top left corner);
                    \pgfgetlastxy{\temptopleftx}{\temptoplefty}
                    \path (\tikzlastnode.top right corner);
                    \pgfgetlastxy{\temptoprightx}{\temptoprighty}
                    \fill[#1!75!black] (\tikzlastnode.top left corner) --     
                    (\tikzlastnode.top right corner) -- 
                    ([shift={(0,{tan(\threedtrapeziumangle)*0.5*(\temptoprightx-\temptopleftx)*1pt})}]\tikzlastnode.top side) --
                    cycle;
                }
            }
        },
        flag/.style={
            rectangle,
            anchor=west,
            yshift=-1ex,
            xshift=3ex,
            left color=#1!50!black,
            right color=transparent!0,
            opacity=.8,
            text opacity=1,
            align=left,
            text width=17.5em,
            text height=.8em,
            text depth=.2em,
            execute at begin node=\hspace{1cm},
        },
        ]
        
        \node[flag=red] at (0,0) (f-1) {5. Unternehmensebene};
    \node[3d trapezium=red, triangle cap=red, minimum width={3cm*sin(65)}] at (0,0) (a-1) {ERP};
    
    \node[flag=orange] at ({1*cos(65)},{-1*sin(65)}) (f-2) {4. Betriebsleitebene};
    \node[3d trapezium=orange, minimum width={2cm*sin(65)}] at (0,{-1*sin(65)}) (a-2) {\small MES, OPC UA};
    
    \node[flag=yellow] at ({2*cos(65)},{-2*sin(65)}) (f-3) {3. Prozessleitebene};
    \node[3d trapezium=yellow, minimum width={3cm*sin(65)}] at (0,{-2*sin(65)}) (a-3) {\small SCADA, PROFIBUS};
    
    \node[flag=green] at ({3*cos(65)},{-3*sin(65)}) (f-4) {2. Steuerungsebene};
    \node[3d trapezium=green, minimum width={5cm*sin(65)}] at (0,{-3*sin(65)}) (a-4) {PLC/SPS, PROFINET};
    
    \node[flag=cyan] at ({4*cos(65)},{-4*sin(65)}) (f-5) {1. Feld-/Prozessebene};
    \node[3d trapezium=cyan, minimum width={7cm*sin(65)}] at (0,{-4*sin(65)}) (a-5) {Sensoren/Aktoren};
    \end{tikzpicture}

编译后,它应该看起来像下面的图片。上例中的颜色与图片不同,以便您更轻松地立即进行编译。

定制金字塔图

如您所见,霓虹绿线表示每个梯形应对齐的角度,如原始示例所示:

以原始金字塔图为例

我尝试调整每个梯形的最小宽度,但结果并不令人满意。您还有其他方法可以让我尝试正确对齐它们吗?

答案1

一些分析,还没有答案,因为有些事情似乎...... //结果是:这个答案在最后确实提供了一个解决方案。

1)代码无法编译

  • 开头(和结尾)缺少一些陈述
  • 你的颜色(secondary1 ..)未定义

2)初步代码,重点关注梯形

这似乎是一个主要问题。一个是:形状梯形并不总是按预期运行。但是,您的代码中存在更多噪音。让我们挑选一行:

\node[3d trapezium...] at (0,0) (a-1) {ERP};

(a-1)似乎没有坏处,但也没有贡献。这是一种备忘录吗?// 嗯,这是一个非常模糊的部分。效果是倒数……但你为什么不把它写成文本,就像这样\node ... {5. Unternehmensebene};

接下来,你要对角度进行大量处理65:是什么决定了这个特殊的值?除非我过度解读了某些内容,否则即使是 3d 梯形也无法定义它。

另外,角度与放置梯形无关,正如您从帮助线网格中看到的那样:它们只是以 (0,0)、(0,-1) ... (0,-4) 为中心放置。

但是,像这样的选项minimum width={7cm*sin(65)}有相关的影响,而其他选项的厘米宽度可能存在“错误”。

结果

\documentclass[10pt,border=3mm,tikz]{standalone}

\usepackage{tikz,pgfplots}
\usetikzlibrary{shapes.geometric}

\begin{document}
\begin{tikzpicture}[
        3d trapezium angle/.code={
            \def\threedtrapeziumangle{#1}
        },
        3d trapezium angle=60,
        3d trapezium/.style={
            shape=trapezium,
            trapezium angle=\threedtrapeziumangle,
            trapezium stretches body=true,
            line width=0pt,
            inner xsep=0pt,
            fill=#1!75!black,
            text=white,
            font=\bfseries,
            text height=.8em,
            text depth=.2em,
            append after command={
                \pgfextra{ 
                    \fill[#1!50!black] (\tikzlastnode.bottom left corner) --     
                    (\tikzlastnode.bottom right corner) -- 
                    ([shift={(-.1,-.33)}]\tikzlastnode.bottom right corner) -- 
                    ([shift={(.1,-.33)}]\tikzlastnode.bottom left corner) --
                    cycle;
                }
            }
        },
        triangle cap/.append style={
            append after command={
                \pgfextra{ 
                    \path (\tikzlastnode.top left corner);
                    \pgfgetlastxy{\temptopleftx}{\temptoplefty}
                    \path (\tikzlastnode.top right corner);
                    \pgfgetlastxy{\temptoprightx}{\temptoprighty}
                    \fill[#1!75!black] (\tikzlastnode.top left corner) --     
                    (\tikzlastnode.top right corner) -- 
                    ([shift={(0,{tan(\threedtrapeziumangle)*0.5*(\temptoprightx-\temptopleftx)*1pt})}]\tikzlastnode.top side) --
                    cycle;
                }
            }
        },
        flag/.style={
            rectangle,
            anchor=west,
            yshift=-1ex,
            xshift=3ex,
            left color=#1!50!black,
            right color=transparent!0,
            opacity=.8,
            text opacity=1,
            align=left,
            text width=17.5em,
            text height=.8em,
            text depth=.2em,
            execute at begin node=\hspace{1cm},
        },
        ]
        
        % !!! undefined colors !!!!
        \colorlet{secondary1}{green}
        \colorlet{secondary2}{green!50}
        \colorlet{secondary3}{blue}
        \colorlet{secondary4}{blue!50}
        \colorlet{secondary5}{blue}
        \colorlet{secondary6}{blue!50}
        
    \draw [help lines] (0,0) grid (5,-5);        
        
 %       \node[flag=secondary1] at (0,0) (f-1) {5. Unternehmensebene};
        \node[3d trapezium=secondary1, triangle cap=secondary1, minimum width={3cm*sin(65)}] at (0,0) (a-1) {ERP};
        
 %       \node[flag=secondary2] at ({1*cos(65)},{-1*sin(65)}) (f-2) {4. Betriebsleitebene};
        \node[3d trapezium=secondary2, minimum width={2cm*sin(65)}] at (0,{-1*sin(65)}) (a-2) {\small MES, OPC UA};
%        
%        \node[flag=secondary3] at ({2*cos(65)},{-2*sin(65)}) (f-3) {3. Prozessleitebene};
        \node[3d trapezium=secondary3, minimum width={3cm*sin(65)}] at (0,{-2*sin(65)}) (a-3) {\small SCADA, PROFIBUS};
%        
%        \node[flag=secondary4] at ({3*cos(65)},{-3*sin(65)}) (f-4) {2. Steuerungsebene};
        \node[3d trapezium=secondary4, minimum width={5cm*sin(65)}] at (0,{-3*sin(65)}) (a-4) {PLC/SPS, PROFINET};
%        
%        \node[flag=secondary5] at ({4*cos(65)},{-4*sin(65)}) (f-5) {1. Feld-/Prozessebene};
       \node[3d trapezium=secondary5, minimum width={7cm*sin(65)}] at (0,{-4*sin(65)}) (a-5) {Sensoren/Aktoren};
    \end{tikzpicture}
\end{document}

3)尝试直觉

那么,为什么不在选项中使用7cm, 6cm...呢?似乎可行 :)3cm

结果

        \node[flag=secondary1] at (0,0) (f-1) {5. Unternehmensebene};
        \node[3d trapezium=secondary1, triangle cap=secondary1, minimum width={3cm*sin(65)}] at (0,0) (a-1) {ERP};
        
        \node[flag=secondary2] at ({1*cos(65)},{-1*sin(65)}) (f-2) {4. Betriebsleitebene};
        \node[3d trapezium=secondary2, minimum width={4cm*sin(65)}] at (0,{-1*sin(65)}) (a-2) {\small MES, OPC UA};
        
        \node[flag=secondary3] at ({2*cos(65)},{-2*sin(65)}) (f-3) {3. Prozessleitebene};
        \node[3d trapezium=secondary3, minimum width={5cm*sin(65)}] at (0,{-2*sin(65)}) (a-3) {\small SCADA, PROFIBUS};
        
        \node[flag=secondary4] at ({3*cos(65)},{-3*sin(65)}) (f-4) {2. Steuerungsebene};
        \node[3d trapezium=secondary4, minimum width={6cm*sin(65)}] at (0,{-3*sin(65)}) (a-4) {PLC/SPS, PROFINET};
       
        \node[flag=secondary5] at ({4*cos(65)},{-4*sin(65)}) (f-5) {1. Feld-/Prozessebene};
       \node[3d trapezium=secondary5, minimum width={7cm*sin(65)}] at (0,{-4*sin(65)}) (a-5) {Sensoren/Aktoren};

4)最终建议

  • 清理节点,即删除(a-1)等。
  • 做一些重构,即统一重复或重复的部分,例如使用\pic\for
  • 帮助我们帮助您:仅发布复制后编译的代码,以防止我们猜测,即让我们专注于您的问题,而不是您的语法

相关内容