假设我有一个三角形,其顶点定义如下
\coordinate (a) at (0,0);
\coordinate (b) at (1,0);
\coordinate (c) at (0,1);
让我们用 表示由和T(x,y)
定义的三角形,该三角形由向量 平移。我现在可以轻松绘制如下图所示:(a),(b)
(c)
(x,y)
T(0,0)
\draw (a) -- (b) -- (c) -- cycle;
到目前为止一切顺利。现在,假设我想绘制三角形T(2,3)
。理想情况下,我想做类似的事情:
\begin{scope}[shift={(2,3)}]
\draw (a) -- (b) -- (c) -- cycle;
\end{scope}
然而,由于坐标是在范围之外定义的,因此变换(在本例中为平移)不会影响它们。参见这个答案。什么是明智的做法?或者更一般地说:
重新使用在不同变换下定义一次的坐标的最佳方法是什么?
可能的解决方案:根据@Qrrbrbirlbel 的评论,我发布了一个答案。然而,这个答案非常有限且具有局部性 - 是否有更通用的东西?
答案1
在 TikZ/pgf 中,变换仅适用于数字坐标。要从node
s 或coordinate
s 检索原始数字坐标,可以使用以下let
操作:
\documentclass[tikz]{standalone}
\usetikzlibrary{calc,scopes}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (1,0);
\coordinate (c) at (0,1);
\draw (a) -- (b) -- (c) -- cycle;
\draw[blue] let \p{a}=(a),\p{b}=(b),\p{c}=(c) in
{[rotate=30] (\p{a}) -- (\p{b}) -- (\p{c}) -- cycle}
{[shift={(2,3)}] (\p{a}) -- (\p{b}) -- (\p{c}) -- cycle};
\end{tikzpicture}
\end{document}
答案2
由于链接中的其他问题已经解释了这个问题,我就不再重复老问题了。查看代码,似乎没有一种简单的方法可以说“将以下样式(例如,shift={(2,3)}
)应用于以下所有点。”。没有every point
样式(对比许多every path
或every node
或......)。此外,添加一个并不简单,因为坐标解析器需要查看才能[
调用执行转换的位(此处的代码uhoh... options!
在这一点上有启发性的注释)。
所以没有真的真的简单的解决方案。但是有一种方法可以使用样式使正确的方法更简单一些。
\documentclass{article}
%\url{http://tex.stackexchange.com/q/98924/86}
\usepackage{tikz}
\tikzset{
c/.style={every coordinate/.try}
}
\begin{document}
\begin{tikzpicture}
\coordinate (A) at (0,0);
\coordinate (B) at (1,0);
\coordinate (C) at (0,1);
\draw (A) -- (B) -- (C) -- cycle;
\begin{scope}[every coordinate/.style={shift={(2,3)}}]
\draw ([c]A) -- ([c]B) -- ([c]C) -- cycle;
\end{scope}
\end{tikzpicture}
\end{document}
显然,样式名称c
可以用其他名称替换,以避免与其他名称(例如坐标名称)混淆。选择单个字母的理由是每次输入时都相对容易,并且该字母c
是“坐标”的缩写。
答案3
添加通用样式并不是一件简单的事情every coordinate
。但是,\iftikztransformnodecoordinates
破解却相当简单。
\documentclass{standalone}
\usepackage{tikz}
\makeatletter
\newif\iftikztransformnodecoordinates
\tikzset{transform node coordinates/.is if=tikztransformnodecoordinates}
\def\tikz@parse@node#1(#2){%
\pgfutil@in@.{#2}%
\ifpgfutil@in@
\tikz@calc@anchor#2\tikz@stop%
\else%
\tikz@calc@anchor#2.center\tikz@stop%
\expandafter\ifx\csname pgf@sh@ns@#2\endcsname\tikz@coordinate@text%
\else
\tikz@shapebordertrue%
\def\tikz@shapeborder@name{#2}%
\fi%
\fi%
\iftikztransformnodecoordinates%
\pgf@pos@transform{\pgf@x}{\pgf@y}%
\fi
\edef\tikz@marshal{\noexpand#1{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}}%
\tikz@marshal%
}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (1,0);
\coordinate (c) at (0,1);
\draw (a) -- (b) -- (c) -- cycle;
\draw [red, transform node coordinates, rotate=10]
(a) -- (b) -- (c) -- cycle;
\draw [green, transform node coordinates, shift={(1,1)}]
(a) -- (b) -- (c) -- cycle;
\draw [blue, transform node coordinates, rotate=10, shift={(1,1)}]
(a) -- (b) -- (c) -- cycle;
\end{tikzpicture}
\end{document}
但不确定它是否 100% 坚固。
答案4
r
那么定义一个应用转换的通用锚点(相对锚点)怎么样?编辑:现在是一个真正有效的版本!
两个问题:
- 调用通用锚点的代码需要节点 cs 中的坐标。
- 相同的代码应用外部变换的逆变换 --- 这就是使命名坐标绝对的原因!
我们的工作是执行所有这些操作的逆操作(按相反的顺序)。
\documentclass{article}
\usepackage{tikz}
\makeatletter
\pgfdeclaregenericanchor{r}{%
% 1. get (x,y) in the node's cs
\pgf@sh@reanchor{\csname pgf@sh@ns@\pgfreferencednodename\endcsname}{center}%
{% 2. apply the node transformation
\pgfsettransform{\csname pgf@sh@nt@\pgfreferencednodename\endcsname}%
\pgf@pos@transform{\pgf@x}{\pgf@y}%
\global\pgf@x=\pgf@x%
\global\pgf@y=\pgf@y%
}%
% 3. *don't* apply the inverse of the outer transformation! We want
% relative coordinates!
{% 4. apply the inverse of the inverse of the outer transform
% (cancels the inverse of the outer transformation done by \pgfpointanchor)
\pgf@pos@transform{\pgf@x}{\pgf@y}%
\global\pgf@x=\pgf@x%
\global\pgf@y=\pgf@y%
}%
{% 5. apply the inverse of the nodes transformation (cancels the node
% transformation done by \pgfpointanchor)
\pgfsettransform{\csname pgf@sh@nt@\pgfreferencednodename\endcsname}%
\pgftransforminvert
\pgf@pos@transform{\pgf@x}{\pgf@y}%
\global\pgf@x=\pgf@x%
\global\pgf@y=\pgf@y%
}%
}
\makeatother
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (1,0);
\coordinate (c) at (0,1);
\draw[blue,ultra thick] (a) -- (b) -- (c) -- cycle;
\begin{scope}[shift={(2,0)},scale=2]
\draw[red] (a.r) -- (b.r) -- (c.r) -- cycle;
\end{scope}
\end{tikzpicture}
\end{document}