我最近发布了一个问题使用 TikZ 绘制 DNA 序列的显示问题。我描述的问题大部分都已解决,但仍有一个问题。我设法简化了我的示例,以更清楚地显示该问题。请考虑以下代码。
在此代码中,两个多部分矩形之间绘制的线两侧都有箭头。我没想到左边会有箭头。请注意,左边的箭头指向向上。删除two north
会使左箭头消失。
现在,如果添加了选项shorten >=1cm
,那么我们只会看到一个向上的箭头尖漂浮在空间中,与右侧的缩短箭头处于同一水平。如果我们改为这样做shorten <=1cm, shorten >=1cm
,那么两端的线条正确终止处都会有箭头,左侧箭头像以前一样指向上方。
在所有这些情况下,普通矩形的行为都是符合预期的。
有人能解释这种行为吗?
\documentclass[preview]{standalone}
\usepackage{tikz}
\usepackage[skip=2pt]{caption}
\usetikzlibrary{shapes, arrows}
\settowidth{\textwidth}{Multipart rectangles with no line shortening}
\begin{document}
\centering
\begin{tikzpicture}
\tikzstyle{line} = [draw, -latex']
% Multipart rectangle nodes
\tikzstyle{seq}=[rectangle split, rectangle split horizontal, rectangle split parts=#1, draw]
\node [seq=3] (leftrow1) at (0cm, 4cm){};
\node [seq=3] (tripletoprow) at (4cm, 4cm){};
% Add arrows on the top
%\path [line, shorten >=1cm] (leftrow1.two north) edge[out=90, in=90] node {}(tripletoprow);
%\path [line, shorten <=1cm, shorten >=1cm] (leftrow1.two north) edge[out=90, in=90] node {}(tripletoprow);
%\path [line, shorten <=1cm] (leftrow1.two north) edge[out=90, in=90] node {}(tripletoprow);
\path [line] (leftrow1.two north) edge[out=90, in=90] node {}(tripletoprow);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Regular rectangle nodes
%\tikzstyle{seq}=[rectangle, draw]
% Regular rectangle nodes
%\node [seq] (leftrow1) at (0cm, 4cm){};
%\node [seq] (tripletoprow) at (4cm, 4cm){};
% Add arrows on the top
%\path [line, shorten >=1cm] (leftrow1) edge[out=90, in=90] node {}(tripletoprow);
%\path [line, shorten <=1cm, shorten >=1cm] (leftrow1) edge[out=90, in=90] node {}(tripletoprow);
%\path [line, shorten <=1cm] (leftrow1) edge[out=90, in=90] node {}(tripletoprow);
%\path [line] (leftrow1) edge[out=90, in=90] node {}(tripletoprow);
\end{tikzpicture}
\captionof{figure}{Multipart rectangles with no line shortening}
\end{document}
答案注释:感谢 percusse 回答了这个问题。我在这里添加了一些关于答案的注释。在这种情况下,阅读文档会很有帮助。:-) PGF/TikZ 手册edge
在第 16.12 节(从第 197 页开始)记录了该操作。在本节(第 197 页)的开头,手册说:
边操作的工作方式类似于在绘制主路径后添加的 to 操作,就像在绘制主路径后添加节点一样。这允许您让每条边具有不同的外观。
重点是“在主路径绘制后添加”这一点。让我们看看我示例中的路径,即
\path [line] (leftrow1.two north) edge[out=90, in=90] node {}(tripletoprow);
我的想法是绘制一条从节点leftrow1
到节点以箭头终止的路径tripletoprow
。
事实上,两条路径被绘制了。我不知道 TikZ 是如何解析这段代码的,但既然命令edge
是在“主路径绘制之后”添加的,那么“主路径”是什么?嗯,它必须在边缘之前,所以必须是
\path [line] (leftrow1.two north) node {};
如果您仅绘制此图形,您将看到只生成了一个箭头,从多部分矩形指向北方leftrow1
。如果删除,则不会出现此箭头node {}
。我不确定为什么。无论如何,关键是这是一条长度为零的路径。它开始和终止于(leftrow1.two north)
并表现为箭头。所以,这是第一条路径。绘制的第二条路径是边缘,它也是一条以箭头为终点的路径,因为(第 198 页)
可以看出,边缘操作的路径继承了主路径的选项,但您可以在本地否决它们。
因此,两侧带有箭头的奇怪路径实际上是两条路径,一条长度为零,一条长度不为零,但两条路径都以箭头结尾。使用缩短不会改变任何东西。它只是将所有内容向上移动了一点。
那么,应该如何解决这个问题?最简单的方法就是不要使用edge
。在这里使用它并不是正确的选择。只需使用
\path [line] (leftrow1.two north) to[out=90, in=90] node {}(tripletoprow);
意味着只会绘制一条路径 - 不绘制零长度路径。或者,可以抑制零长度路径的绘制并保留边缘操作,例如
\path [] (leftrow1.two north) edge[out=90, in=90, line] node {}(tripletoprow);
但这无疑是两种选择中不太自然的一种。
最后一件事 - 我写了
在所有这些情况下,普通矩形的行为都是符合预期的。
事实并非如此。在我发布的普通(非多形状)矩形示例中没有看到这种行为的原因是north
那里没有使用锚点。因此,例如,如果我们替换
\path [line] (leftrow1) edge[out=90, in=90] node {}(tripletoprow);
和
\path [line] (leftrow1.north) edge[out=90, in=90] node {}(tripletoprow);
我们看到了同样的行为。
答案1
好吧,这个有点奇怪,但我想我知道发生了什么。让我稍微绕个弯:考虑以下结构
\draw (0,0) -- (1,1) node (a) {A};.
我们希望这段代码在创建主路径后放置一个节点。请注意,节点不知道路径的性质。即使我们使用[pos=0.xx]
它,也只是寻找最后一条可用路径,因此节点放置和路径创建之间没有有机联系。
事实证明,这edge
是一个to
以类似方式添加的操作,与之前构建的主路径没有任何关系。另一个示例(放大)
\begin{tikzpicture}
\path[->,
draw,
line width=1mm % To make the arrowhead bigger
] (0,0);
\end{tikzpicture}
因此,箭头的路径长度为零。如果我们剖析其中一条路径,边缘也会发生同样的情况
\path [line] (leftrow1.two north) % This is the main path as the example above
edge[out=90, in=90] node {}(tripletoprow); % This is added afterwards without the
% line option in place creating the
% illusion that the path is having
% a disconnected arrowhead
line
因此缩短会使情况变得更糟,因为它会缩短零长度路径,使箭头更远。一旦我们解决了问题,那么通过将选项转移到edge
;来轻松解决问题就很容易了
\documentclass[preview,tikz,border=3mm]{standalone}
\usetikzlibrary{shapes, arrows}
\tikzset{line/.style={draw, latex'-},
seq/.style={rectangle split, rectangle split horizontal, rectangle split parts=#1, draw}
}
\begin{document}
\begin{tikzpicture}
\node [seq=3] (leftrow1) at (0cm, 4cm){};
\node [seq=3] (tripletoprow) at (4cm, 4cm){};
\path (leftrow1.two north) edge[out=90, in=90,line] (tripletoprow);
\end{tikzpicture}
\end{document}
另请参阅手册进行操作,以避免目标点之前的\tikztonodes
多余部分。node{}
答案2
这其实不是问题,但这是一个非常好的功能。要获取主路径,您只需删除edge[options] (a,b)
例子 :
- 主路径为
\draw[blue,->] (0,0) edge[red] (3,0)
(0,0) - 在
\draw[blue,->] (0,0) edge[red] (3,0) to (1,1);
主路径中(0,0) to (1,1)
\draw (0,0) edge [out=60,in=60,red,->] (4,0) edge [blue,-o] (2,3);
主路径 (0,0)\draw[blue,->] (0,0) to (1,0) edge [red,dashed] (2,1) to (3,0) edge [red,dashed] (4,1) to (5,0);
主路径(0,0) to (1,0) to (3,0) to (5,0)
结论: 中的选项\draw
应用于主路径,edge
就像绘制命令后将节点添加到主路径一样。
\documentclass[11pt]{scrartcl}
\usepackage{tikz}
\usetikzlibrary{arrows}
\begin{document}
\tikz \draw(0,0) edge [out=60,in=60,red,->] (4,0) edge [blue,-o] (2,3);
\tikz \draw[blue,->] (0,0) to (1,0) edge [red,dashed] (2,1)
to (3,0) edge [red,dashed] (4,1)
to (5,0);
\tikz \draw[blue,->] (0,0) edge[red] (3,0) to (1,1);
\end{document}