3D 块和流程图

3D 块和流程图

这是第二次尝试重现下图。在此处输入图片描述

有人建议我使用fit库,我尝试了一下,得到了以下结论:

\documentclass[tikz]{standalone}

%% Language and font encodings
\usepackage[english]{babel}
\usepackage[utf8x]{inputenc}
\usepackage[T1]{fontenc}
\usetikzlibrary {fit}

\usepackage{xcolor}
\definecolor{darkblue}{HTML}{1f4e79}
\definecolor{lightblue}{HTML}{00b0f0}
\definecolor{salmon}{HTML}{ff9c6b}

\usetikzlibrary{backgrounds,calc,shadings,shapes.arrows,arrows,shapes.symbols,shadows,positioning,decorations.markings,backgrounds,arrows.meta}

% Define parallelepiped shape:
\makeatletter
\pgfkeys{/pgf/.cd,
  parallelepiped offset x/.initial=2mm,
  parallelepiped offset y/.initial=2mm
}
\pgfdeclareshape{parallelepiped}
{
  \inheritsavedanchors[from=rectangle] % this is nearly a rectangle
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{mid}
  \inheritanchor[from=rectangle]{mid west}
  \inheritanchor[from=rectangle]{mid east}
  \inheritanchor[from=rectangle]{base}
  \inheritanchor[from=rectangle]{base west}
  \inheritanchor[from=rectangle]{base east}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchor[from=rectangle]{south east}
  \backgroundpath{
    % store lower right in xa/ya and upper right in xb/yb
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/parallelepiped
      offset x}}
    \pgfmathsetlength\pgfutil@tempdimb{\pgfkeysvalueof{/pgf/parallelepiped
      offset y}}
    \def\ppd@offset{\pgfpoint{\pgfutil@tempdima}{\pgfutil@tempdimb}}
    \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
    \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
    \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
    \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
    \pgfpathclose
    \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
    \pgfpathlineto{\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@ya}}{\ppd@offset}}
    \pgfpathlineto{\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@yb}}{\ppd@offset}}
    \pgfpathlineto{\pgfpointadd{\pgfpoint{\pgf@xa}{\pgf@yb}}{\ppd@offset}}
    \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
    \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
    \pgfpathlineto{\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@yb}}{\ppd@offset}}
  }
}
\makeatother

\tikzset{
  % Dark blue blocks
  block/.style={
    parallelepiped,fill=white, draw,
    minimum width=0.2cm,
    minimum height=3.2cm,
    parallelepiped offset x=0.5cm,
    parallelepiped offset y=0.5cm,
    path picture={
      \draw[top color=darkblue,bottom color=darkblue]
        (path picture bounding box.south west) rectangle 
        (path picture bounding box.north east);
    },
    text=white,
  },
  % many
   block2/.style={
    parallelepiped,fill=white, draw,
    minimum width=0.3cm,
    minimum height=2.7cm,
    parallelepiped offset x=0.5cm,
    parallelepiped offset y=0.5cm,
    path picture={
      \draw[top color=darkblue,bottom color=darkblue]
        (path picture bounding box.south west) rectangle 
        (path picture bounding box.north east);
    },
    text=white,
  },
  %last
    block3/.style={
    parallelepiped,fill=white, draw,
    minimum width=0.3cm,
    minimum height=1.7cm,
    parallelepiped offset x=0.5cm,
    parallelepiped offset y=0.5cm,
    path picture={
      \draw[top color=darkblue,bottom color=darkblue]
        (path picture bounding box.south west) rectangle 
        (path picture bounding box.north east);
    },
    text=white,
  },
 % Orange-ish blocks
  conv/.style={
    parallelepiped,fill=white, draw,
    minimum width=0.8cm,
    minimum height=1.0cm,
    parallelepiped offset x=0.1cm,
    parallelepiped offset y=0.1cm,
    path picture={
      \draw[top color=salmon,bottom color=salmon]
        (path picture bounding box.south west) rectangle 
        (path picture bounding box.north east);
    },
    text=white,
  },
  % Orange-ish blocks
  conv2/.style={
    parallelepiped,fill=white, draw,
    minimum width=0.4cm,
    minimum height=1.0cm,
    parallelepiped offset x=0.5cm,
    parallelepiped offset y=0.5cm,
    path picture={
      \draw[top color=salmon,bottom color=salmon]
        (path picture bounding box.south west) rectangle 
        (path picture bounding box.north east);
    },
    text=white,
  },
  % Taller Light blue blocks:
  plate/.style={
    parallelepiped,fill=white, draw,
    minimum width=0.09cm,
    minimum height=3.1cm,
    parallelepiped offset x=0.5cm,
    parallelepiped offset y=0.5cm,
    path picture={
      \draw[top color=lightblue,bottom color=lightblue]
        (path picture bounding box.south west) rectangle 
        (path picture bounding box.north east);
    },
    text=white,
  },
  % style
   % Taller Light blue blocks:
  plate2/.style={
    parallelepiped,fill=white, draw,
    minimum width=0.1cm,
    minimum height=2.5cm,
    parallelepiped offset x=0.5cm,
    parallelepiped offset y=0.5cm,
    path picture={
      \draw[top color=lightblue,bottom color=lightblue]
        (path picture bounding box.south west) rectangle 
        (path picture bounding box.north east);
    },
    text=white,
  },
  % Arrows between blocks:
  link/.style={
    color=white,
    line width=1mm,
  },
  link2/.style={
    color=lightblue,
    line width=1mm,
  },
}

\begin{document}

\begin{tikzpicture}
  % The order of blocks matters since some are partially hidden behind subsequent blocks.

  \node[conv](conv1) {\rotatebox{90}{Train Data}};
   
 \node[conv, above=0.9cm of conv1 ](conv3) 
  {\rotatebox{90}{Generator}};
    \node[conv, below=0.9cm of conv1 ](conv2) 
  {\rotatebox{90}{Ref. Data }};
  
  % \node[plate,right=4.9cm of conv1](plate1){};
  % yshift to align the bottom of that blocks with the previous taller block.
  \node[block,right=3.cm of conv1,yshift=0.001cm](resblock1){\rotatebox{90}{1}};

    \draw [-triangle 60,link2] ([xshift=0.1cm,yshift=0.2cm]conv1.east) -- ([xshift=0.0cm,yshift=0.2cm]resblock1.west);
  
  \node[block,right=0.1cm of resblock1](resblock2){\rotatebox{90}{1}};
  
  % \node[block,above=0.1cm of resblock1](resblock2){\rotatebox{90}{2}};
  % \node[block,above=0.1cm of resblock2](resblock3){\rotatebox{90}{3}};
  % \node[block,right=0.2cm of resblock1](x1){\rotatebox{90}{(X4)}};
  % \node[block,above=0.1cm of x1](x2){\rotatebox{90}{Dense Layer}};
  % \node[block,above=0.1cm of x2](x3){\rotatebox{90}{(X2)}};
  \node[plate,right=0.2cm of resblock2](plate2){\rotatebox{90}{BatchNorm}};
  \node[block2,right=0.2cm of plate2](resblock4){\rotatebox{90}{ResBlock4}};
  \node[block2,right=0.1cm of resblock4](resblock6){\rotatebox{90}{ResBlock6}};

\node[plate2,right=0.2cm of resblock6](plate3){\rotatebox{90}{\small BatchNorm}};;

  \node[block3,right=0.3cm of plate3](resblock5){\rotatebox{90}{ \small
 ResBlock5}};
 
  
  \node[conv2,right=0.2cm of resblock5](last){\rotatebox{90}{Conv}};
   \node[draw=red,very thick,   fit=(resblock1) (resblock1) (plate2) (resblock4) (resblock4) (plate3) (resblock5) (last)  ](fitter) {};
  % \draw [-,link] ([xshift=0.2cm,yshift=0.2cm]last.east) -- ([yshift=0.2cm]last.west);
% \node[below] at (fit.south) {box};
 \node[above] at (fitter.south) {box};
  \node[below] at (fitter.north) {box};
\draw [link] ([xshift=1.cm,yshift=0.2cm]last.east) -- ([xshift=1.5cm,yshift=0.2cm]last.east) ;

\draw [-triangle 60,link2] ([xshift=0.1cm,yshift=0.2cm]fitter.west) -- ([xshift=0.0cm,yshift=0.2cm]conv3.east);

\draw [-triangle 60,link2] ([xshift=0.0cm,yshift=0.0cm]conv3.south) -- ([xshift=0.0cm,yshift=0.0cm]conv1.north);

\draw [-triangle 60,link2] ([xshift=0.0cm,yshift=0.0cm]conv2.north) -- ([xshift=0.0cm,yshift=0.0cm]conv1.south);

\end{tikzpicture}

\end{document}

这是受到此处解决方案的启发使用 TikZ 制作堆叠的 3D 块以及此处解决方案的建议流程图和 3D 图表 tikz

我现在得到的输出如下:

在此处输入图片描述

我想要 :

  1. 正确添加箭头并适当格式化以适合矩形
  2. 添加相应的文本。

谢谢

答案1

  1. 我将您的风格浓缩为以下几种:

    • 具有block最常见设置的通用设置(形状及其偏移,drawtext = white),
    • plate和 block 一样,但是fill颜色lightblue不是darkblue
    • conv它们是更薄的(→偏移量较小)橙色块。

    那么,它们有三种尺寸:size 1size 2size 3

  2. 我没有手动将所有节点放置在fit框内,而是使用chains具有自定义bottom right放置规则的库,使节点底部对齐。

    此规则是通过使用start chain = going bottom right然后放置每个节点来设置的on chain

  3. 我们现在可以使用两个嵌套\foreach循环来放置节点,外循环通过其自己的计数器确定其大小\CNT,内循环遍历每个大小组并\node使用适当的位置实际放置 s \STYLE

  4. 虽然chains库隐式地为节点提供了别名,但我们仍然需要手动为它们提供明确的名称,以便我们能够实际使用样式的效果,every parallelepiped node该样式将坐标放置在框的(真实)右上角。(最好改进形状并添加真正的锚点,但现在就这样了。)

  5. 在键的值中,fit我们不仅使用第一个节点的裸名称gr1-1,还使用这些坐标gr1-1-North East,并且gr3-2-North East我们知道它们包含所有内容。

  6. outer sep其设置为零后,我们现在可以使用矩形的四边来添加文本、箭头和坐标box-ne以供以后使用。

  7. 左侧的树框已添加。

  8. 所有边均被绘制。

代码

\documentclass[tikz]{standalone}
\usepackage[english]{babel}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\definecolor{darkblue}{HTML}{1f4e79}
\definecolor{lightblue}{HTML}{00b0f0}
\definecolor{salmon}{HTML}{ff9c6b}
\definecolor{buff}{RGB}{218, 160, 109}
\usetikzlibrary{backgrounds, chains, fit, positioning, arrows.meta, quotes}
% Define parallelepiped shape:
\pgfset{
  parallelepiped offset x/.initial=2mm,
  parallelepiped offset y/.initial=2mm}
\makeatletter
\pgfdeclareshape{parallelepiped}{%
  \inheritsavedanchors[from=rectangle] % this is nearly a rectangle
  \inheritanchorborder[from=rectangle]
  \inheritanchor[from=rectangle]{north}
  \inheritanchor[from=rectangle]{north west}
  \inheritanchor[from=rectangle]{north east}
  \inheritanchor[from=rectangle]{center}
  \inheritanchor[from=rectangle]{west}
  \inheritanchor[from=rectangle]{east}
  \inheritanchor[from=rectangle]{mid}
  \inheritanchor[from=rectangle]{mid west}
  \inheritanchor[from=rectangle]{mid east}
  \inheritanchor[from=rectangle]{base}
  \inheritanchor[from=rectangle]{base west}
  \inheritanchor[from=rectangle]{base east}
  \inheritanchor[from=rectangle]{south}
  \inheritanchor[from=rectangle]{south west}
  \inheritanchor[from=rectangle]{south east}
  \backgroundpath{%
    % store lower right in xa/ya and upper right in xb/yb
    \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
    \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
    \pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/parallelepiped offset x}}%
    \pgfmathsetlength\pgfutil@tempdimb{\pgfkeysvalueof{/pgf/parallelepiped offset y}}%
    \def\ppd@offset{\pgfpoint{\pgfutil@tempdima}{\pgfutil@tempdimb}}%
    \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}%
    \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}%
    \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}%
    \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}%
    \pgfpathclose
    \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@ya}}%
    \pgfpathlineto{\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@ya}}{\ppd@offset}}%
    \pgfpathlineto{\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@yb}}{\ppd@offset}}%
    \pgfpathlineto{\pgfpointadd{\pgfpoint{\pgf@xa}{\pgf@yb}}{\ppd@offset}}%
    \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}%
    \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}%
    \pgfpathlineto{\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@yb}}{\ppd@offset}}%
  }
}
\makeatother

\tikzset{
  block/.style={
    shape=parallelepiped,
    fill=darkblue, draw, text=white,
    parallelepiped offset x=0.5cm,
    parallelepiped offset y=0.5cm},
  size 1/.style={minimum width=0.2cm, minimum height=3.2cm},
  size 2/.style={minimum width=0.3cm, minimum height=2.7cm},
  size 3/.style={minimum width=0.3cm, minimum height=1.7cm},
 % Orange-ish blocks
  conv/.style={block, minimum width=0.8cm, minimum height=1.0cm,
    fill=salmon, parallelepiped offset x=0.1cm, parallelepiped offset y=0.1cm},
  % Taller Light blue blocks:
  plate/.style={block, fill=lightblue},
}
\tikzset{% https://tex.stackexchange.com/a/674354/16595
  pics/arrow/.style={/tikz/sloped, /tikz/allow upside down,
    code=\pgfarrowdraw{#1}}, pics/arrow/.default=>,
  every parallelepiped node/.style={
    label/.expanded={[shape=coordinate,name=\noexpand\tikzlastnode-North East,
      xshift={\pgfkeysvalueof{/pgf/parallelepiped offset x}},
      yshift={\pgfkeysvalueof{/pgf/parallelepiped offset y}}]north east:}},
  bottom right/.style={right=#1.south east, anchor=south west}}
\begin{document}

\begin{tikzpicture}[
  > = {Triangle[angle'=45, scale=.5]},
  |-/.style={to path=|-(\tikztotarget)\tikztonodes}
]
\newcommand*\rot[1]{\rotatebox{90}{#1}}
\begin{scope}[start chain=going bottom right, node distance=2mm]
\foreach[count=\CNT] \GROUP in {
  {block/1,         block/1,         plate/BatchNorm},
  {block/ResBlock4, block/ResBlock6, plate/BatchNorm},
  {block/ResBlock5,                  conv/Conv}}
  \foreach[count=\CCNT] \STYLE/\TEXT in \GROUP
    \node[on chain, size \CNT/.try, \STYLE] (gr\CNT-\CCNT) {\rot{\TEXT}};
\end{scope}

\tikzset{line width=1mm}
\node[
  fit=(gr1-1)(gr1-1-North East)(gr3-2-North East),
  rounded corners=+5mm, draw,
  inner sep=+8mm, outer sep=+0pt] (box) {};
\path[pos=.6] (box.north east) -- node[below, buff] {Some text, some text}
                                  pic               {arrow}
                                  coordinate[pos=.2] (box-ne) (box.north west);
\path[at end, every pic/.append style={xshift=-5mm}]
  (box.north west) -- pic{arrow} (box.south west)
  (box.south east) -- pic{arrow} (box.north east);

\tikzset{node distance=.9cm and 2cm}
\node[conv, left =of box      ] (trainData) {\rot{Train Data}};
\node[conv, above=of trainData] (generator) {\rot{Generator}};
\node[conv, below=of trainData] (refData)   {\rot{Ref. Data}};

\path[->] (generator) edge (trainData)
          (refData)   edge (trainData)
 [nodes=buff]
          (box-ne)    edge[|-, "Some text"' near end] (generator)
          (trainData) edge[buff!50!black, shorten >=2mm, shorten <=2mm,
                           "Text", "Text"'] (box)
;
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

相关内容