我编写了一个宏来在 tikz 中进行一些绘图,我希望能够在任意位置调用它(我认为这些位置称为节点?)
我尝试使用相对定位来编写坐标,但是当我调用它时,我的图表相互重叠。
我不确定我是否误解了节点语法或相对坐标。
\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\newcommand{\Register[1]}{
\fill [gray] +(0,0) rectangle +(4,1);
\fill [pink] +(4,0) rectangle +(8,1);
\draw [thick]
+(0,0) -- +(8,0) -- +(8,1) -- +(0,1) -- cycle;
\draw [thick]
+(0,0) +(4,0) -- +(4,1);
\draw [thin, dashed]
+(0,0) +(2,0) -- +(2,1) +(6,0) -- +(6,1);
\draw [very thin, dotted]
+(0,0) +(1,0) -- +(1,1) +(3,0) -- +(3,1)
+(5,0) -- +(5,1) +(7,0) -- +(7,1);
\node [above right] at +(0,1) {#1};
}
\begin{document}
\begin{tikzpicture}
\node (a) {A};
\Register[R\textsubscript{1}];
\node [below=of a] {B};
\Register[R\textsubscript{2}]
\end{tikzpicture}
\end{document}
答案1
相对坐标是相对于前一个位置的在当前路径中在路径的开始处,前一个位置始终是 (0,0)。
因此,您必须提供一个参考坐标(命令的新参数)并在每个路径的开头使用它。
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\newcommand\Register[2]{
\fill [gray] (#1) +(0,0) rectangle +(4,1);
\fill [pink] (#1) +(4,0) rectangle +(8,1);
\draw [thick]
(#1) +(0,0) -- +(8,0) -- +(8,1) -- +(0,1) -- cycle;
\draw [thick]
(#1) +(0,0) +(4,0) -- +(4,1);
\draw [thin, dashed]
(#1) +(0,0) +(2,0) -- +(2,1) +(6,0) -- +(6,1);
\draw [very thin, dotted]
(#1) +(0,0) +(1,0) -- +(1,1) +(3,0) -- +(3,1)
+(5,0) -- +(5,1) +(7,0) -- +(7,1);
\path (#1) +(0,1) node [above right] {#2};
}
\begin{document}
\begin{tikzpicture}
\node (a) {A};
\Register{a}{R\textsubscript{1}};
\node [below=of a] (b) {B};
\Register{b}{R\textsubscript{2}}
\end{tikzpicture}
\end{document}
答案2
这看起来很可怕,但除非你必须旋转节点,否则我会采用这种path picture
方法:
它允许列出框,即
4/gray, 4/pink
表示四个灰色方块和四个粉色方块。(实际上,它们被绘制为一个矩形,以隐藏一些不幸的渲染伪影。)
这个长方形的高为
register/height
,宽为<number of boxes> * register/width
。这使您可以更改节点的大小,而不必将它们硬编码到样式中。
需要三个循环:
- 助手
.list
会dim list
评估需要多少个盒子,并minimum width
相应地设置节点。 - 第一个
\foreach
步骤是遍历用户给定的列表。 - 第二个
\foreach
绘制垂直线。
(这\the\numexpr\registerNodeWidth-1\relax
使得最后一条落在节点右边界上的线不会被绘制。无论如何它都会在节点的边界下。)
- 助手
该
[style/.expand once=\Color]
命令\fill
允许在列表中使用任意样式,例如{ 1/red, 1/{left color=red, right color=blue!50}, 1/{left color=blue!50, right color=green}, 1/green, 1/{pattern=crosshatch, pattern color=gray} }
当然,也包括你自己的。
不是
label
的一部分,当您通过或类似物register node
放置节点时将不会被考虑。below=of …
如果您希望寄存器左对齐,那么除了手动执行之外below=of ….south west, anchor=north west
,还有其他选项,例如\matrix
将所有节点放置在其中anchor=west
。
代码
\documentclass[tikz, border=5pt, convert]{standalone}
\usetikzlibrary{patterns, shadings, positioning, ext.misc}
\pgfkeys{
/utils/dim list/.style={
/utils/exec=\def\registerNodeWidth{0},
/utils/@dim list/.list={#1}},
/utils/@dim list/.code args={#1/#2}%
{\edef\registerNodeWidth{\the\numexpr\registerNodeWidth+#1}}}
\tikzset{
draw,
register/width/.initial=1cm, register/height/.initial=1cm,
register/dotted/.style={dotted}, register/dashed/.style={dashed},
every register node/.style={draw, thick},
register node/.value required,
register node/.style 2 args={
shape=rectangle, every register node, /utils/dim list={#2},
minimum width=\registerNodeWidth*\pgfkeysvalueof{/tikz/register/width},
minimum height=\pgfkeysvalueof{/tikz/register/height},
path picture={
\foreach[
remember=\totalWidth as \lastTotalWidth (initially 0),
evaluate={\totalWidth=\lastTotalWidth+\Width;}]
\Width/\Color in {#2}
\fill[style/.expand once=\Color]
([xshift=\lastTotalWidth*\pgfkeysvalueof{/tikz/register/width}]%
path picture bounding box.south west)
rectangle ++(\Width*\pgfkeysvalueof{/tikz/register/width},
\pgfkeysvalueof{/tikz/register/height});
\foreach \cnt in {1,...,\the\numexpr\registerNodeWidth-1\relax}
\draw[every register node,
/utils/if={mod(\cnt,2)}{register/dotted},
/utils/if={mod(\cnt,4)==2}{register/dashed}]
([xshift=\cnt*\pgfkeysvalueof{/tikz/register/width}]%
path picture bounding box.south west)
-- ++ (up:\pgfkeysvalueof{/tikz/register/height});
},
label={[anchor=south west]north west:$#1$}}}
\begin{document}
\begin{tikzpicture}
\node [register node={R_1}{4/gray, 4/pink}] (A) {};
\node[below=of A] [register node={R_2}{3/gray, 2/pink, 3/magenta}] (B) {};
\node[below=of B] [register node={R_3}{
1/red,
1/{left color=red, right color=blue!50},
1/{left color=blue!50, right color=green},
1/green,
1/{pattern=crosshatch, pattern color=gray}
}] (C) {};
\end{tikzpicture}
\end{document}