我正在制作一个包,我想绘制类似以下的结构:
它有 2 个节点。小圆形节点位于矩形节点边界上的某个锚点处,经过调整,使其中心与矩形轮廓线的总高度或宽度(视情况而定)的中间对齐。在此特定情况下,圆形节点位于矩形节点north
的锚点处,按照所述进行调整。
如果我做了显而易见的事情并将圆形节点放置在矩形节点的适当锚点处,
\node (x) [text node] at (0,1) {Hello World};
\node [circ node] at (x.north) {};
我明白了
这不是我想要的。
我可以强制outer sep=0pt
使用矩形节点,如安德鲁·斯旺。但是,我还需要绘制节点之间的连接,并且我希望人们能够以标准方式绘制其他连接。因此,这实际上不是一个选择。
我可以通过使用来获得我想要的结果
\node (t) [text node] {Hello World};
\pgflinewidthsaved=\pgflinewidth
\pgflinewidth=0pt
\node (p) [text node, phantom] at (t.center) {\phantom{Hello World}};
\node (c) [circ node] at (p.north) {};
\pgflinewidth=\pgflinewidthsaved
样式phantom
定义如下
phantom/.style={line width=0pt, fill=none, draw=none, anchor=center},
为了确保匹配,我必须将主节点的样式应用于幻像节点,然后覆盖幻像节点中的相关设置。但是,这非常脆弱,而且有点棘手。例如,我需要消除任何xshift
、等yshift
,shift
以便它有机会,而这不能通过将它们设置为零来实现,因为这些东西是累积的。
有没有更好的方法来实现这种构造?例如,是否有可能创建一个形状的修改版本rectangle
,该版本将具有考虑线宽的附加锚点?我查看了代码,rectangle
但我不知道它是如何与线宽一起编译的,也不知道在哪里进行调整。(我认为除了延迟、边框锚点等之外,形状或多或少是静态存储的,因此这是不可能的,但我不确定。)或者是否有可能以任何其他相对合理和更精简的方式来做到这一点?
请注意,我在此处提供的代码已大大简化。在实际情况中,我不知道应在矩形节点的哪个锚点处放置圆形节点。我也不知道勾勒出矩形节点的线的宽度,或者是否有任何线勾勒出它的轮廓。也就是说,line width
可以为矩形节点指定任何值,包括0pt
。因此,我不能只是稍微移动圆形节点,因为我不知道要移动多少或朝哪个方向移动它。我也不知道矩形节点的大小,或者它是否相对于其他东西放置。(我知道它是用语法放置的\node ... at (...) ...
。)我不知道是否对节点应用了任何转换,例如xshift
,rotate
或其他什么。
但是,如果必要的话,我准备禁止使用rotate
,而且我当然不希望它能与任何奇怪的事情一起工作,例如画布变换或坐标系切换。但我确实需要它与诸如 之类的东西一起工作xshift
。现在,我只是想放弃这些,但我不确定我是否有一个好的策略来做到这一点。(也就是说,我有一个策略,但它假设人们会阅读文档,而我宁愿它不读。)
平均能量损失
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\newdimen\pgflinewidthsaved
\begin{document}
\begin{tikzpicture}
[
opacity=.5,
text node/.style={draw, line width=2pt, anchor=north},
phantom/.style={line width=0pt, fill=none, draw=none, anchor=center},
circ node/.style={fill, anchor=center, circle, minimum size=4pt, inner sep=0pt},
]
\node (t) [text node] {Hello World};
\pgflinewidthsaved=\pgflinewidth
\pgflinewidth=0pt
\node (p) [text node, phantom] at (t.center) {\phantom{Hello World}};
\node (c) [circ node] at (p.north) {};
\pgflinewidth=\pgflinewidthsaved
\node (x) [text node] at (0,1) {Hello World};
\node [circ node] at (x.north) {};
\node [font=\itshape, anchor=mid west] at (x.mid east) {default --- not wanted};
\node [font=\itshape, anchor=mid west] at (t.mid east) {wanted --- not default};
\end{tikzpicture}
\end{document}
答案1
下面的代码定义了一系列称为middle north east
、middle south west
等的锚点。
这些锚点独立于原始锚点工作。您可以同时使用它们。PGF 转换和画布转换照常工作。
但是,只能有一个\pgfpointanchorborder
。因此您必须使用\tikzset{middle anchorborder=true/false}
来打开/关闭它。
\documentclass[border=9pt,tikz]{standalone}
\begin{document}
\makeatletter
\def\pgf@sm@shape@name{rectangle}
\pgf@sh@savedanchor\middlenortheast{%
\pgf@x=\the\wd\pgfnodeparttextbox%
\pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}\advance\pgf@x by 2\pgf@xc%
\pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/minimum width}}\ifdim\pgf@x<\pgf@xb\pgf@x=\pgf@xb\fi%
\pgf@x=.5\pgf@x\advance\pgf@x by.5\wd\pgfnodeparttextbox%
\pgf@y=\ht\pgfnodeparttextbox\advance\pgf@y by\dp\pgfnodeparttextbox%
\pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/inner ysep}}\advance\pgf@y by 2\pgf@yc%
\pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/minimum height}}\ifdim\pgf@y<\pgf@yb\pgf@y=\pgf@yb\fi%
\pgf@y=.5\pgf@y\advance\pgf@y by-.5\dp\pgfnodeparttextbox\advance\pgf@y by.5\ht\pgfnodeparttextbox%
}
\pgf@sh@savedanchor\middlesouthwest{%
\pgf@x=\wd\pgfnodeparttextbox%
\pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}\advance\pgf@x by 2\pgf@xc%
\pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/minimum width}}\ifdim\pgf@x<\pgf@xb\pgf@x=\pgf@xb\fi%
\pgf@x=-.5\pgf@x\advance\pgf@x by.5\wd\pgfnodeparttextbox%
\pgf@y=\ht\pgfnodeparttextbox\advance\pgf@y by\dp\pgfnodeparttextbox%
\pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/inner ysep}}\advance\pgf@y by 2\pgf@yc%
\pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/minimum height}}\ifdim\pgf@y<\pgf@yb\pgf@y=\pgf@yb\fi%
\pgf@y=-.5\pgf@y\advance\pgf@y by-.5\dp\pgfnodeparttextbox\advance\pgf@y by.5\ht\pgfnodeparttextbox%
}
\pgf@sh@anchor{middle north east}{\middlenortheast}
\pgf@sh@anchor{middle south west}{\middlesouthwest}
\pgf@sh@anchor{middle south east}{\middlenortheast\pgf@xa=\pgf@x\middlesouthwest\pgf@x=\pgf@xa}
\pgf@sh@anchor{middle north west}{\middlesouthwest\pgf@xa=\pgf@x\middlenortheast\pgf@x=\pgf@xa}
\pgf@sh@anchor{middle north}{
\pgf@process{\middlesouthwest}\pgf@xa=.5\pgf@x\pgf@process{\middlenortheast}\pgf@x=.5\pgf@x\advance\pgf@x by \pgf@xa
}
\pgf@sh@anchor{middle south}{
\pgf@process{\middlenortheast}\pgf@xa=.5\pgf@x\pgf@process{\middlesouthwest}\pgf@x=.5\pgf@x\advance\pgf@x by \pgf@xa
}
\pgf@sh@anchor{middle west}{
\pgf@process{\middlenortheast}\pgf@ya=.5\pgf@y\pgf@process{\middlesouthwest}\pgf@y=.5\pgf@y\advance\pgf@y by \pgf@ya
}
\pgf@sh@anchor{middle east}{%
\pgf@process{\middlesouthwest}\pgf@ya=.5\pgf@y\pgf@process{\middlenortheast}\pgf@y=.5\pgf@y\advance\pgf@y by \pgf@ya
}
\newif\ifmiddleanchorborder
\tikzset{middle anchorborder/.is if=middleanchorborder}
\pgf@sh@anchorborder{
\pgf@xb=\pgf@x\pgf@yb=\pgf@y\ifmiddleanchorborder\middlesouthwest\else\southwest\fi%
\pgf@xa=\pgf@x\pgf@ya=\pgf@y\ifmiddleanchorborder\middlenortheast\else\northeast\fi%
\advance\pgf@x by-\pgf@xa\advance\pgf@y by-\pgf@ya\pgf@xc=.5\pgf@x\pgf@yc=.5\pgf@y%
\advance\pgf@xa by\pgf@xc\advance\pgf@ya by\pgf@yc%
\edef\pgf@marshal{\noexpand\pgfpointborderrectangle
{\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}}%
\pgf@process{\pgf@marshal}\advance\pgf@x by\pgf@xa\advance\pgf@y by\pgf@ya%
}
\tikz[middle anchorborder]{
\node[draw,line width=4,opacity=.5,rotate=30](s){\Huge Bye Bye};
\foreach\anchor in{%
middle north west,%
middle north,%
middle north east,%
middle west,%
middle east,%
middle south west,%
middle south,%
middle south east,%
130
}{
\draw[shift=(s.\anchor)]plot[mark=x]coordinates{(0,0)}node[right]{\tiny\texttt{(s.\anchor)}};
}
}
\end{document}