在 TikZ 中,可以使用库let
的语法calc
或使用 PGF 命令访问节点的坐标值\pgfpointanchor
。但是,这些值是点的尺寸/长度,而不是所用坐标系的值。例如,我喜欢用它们的逻辑坐标值标记图中的某些点和节点,例如在标准中tikzpicture
,即x=1cm,y=1cm
实际上,处的点应该用而不是用(1,2)
标记。节点不是手动定位的,而是使用 TikZ 的各种相对定位技术,所以我自己不知道坐标。这是关于具有正交 X 轴和 Y 轴的普通二维 XY 坐标系。(1,2)
(28.4527pt,56.9055pt)
我目前的做法是获取单位向量的长度(以点为单位),然后用坐标长度除以它,以计算所用坐标系的相应值。这种方法行得通,但当然会导致舍入误差,例如 1.9998 而不是 2。然后我使用函数\num
将siunitx
数字舍入为合适的位数。
我的问题:有没有更好的tikz坐标来实现这一
目标x=1pt,y=1pt
?
在这里,我的概念验证解决方案目前非常僵化,因为它仅适用于节点。
\documentclass[png]{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections}
\usepackage[round-mode=places]{siunitx}
\makeatletter
\newcommand\xcoord[2][center]{{%
\pgfpointxy{1}{1}%
\@tempdima=\pgf@x
\pgfpointanchor{#2}{#1}%
\@tempdimb=\pgf@x
\pgfmathparse{\@tempdimb/\@tempdima}%
\num{\pgfmathresult}%
}}
\newcommand\ycoord[2][center]{{%
\pgfpointxy{1}{1}%
\@tempdima=\pgf@y
\pgfpointanchor{#2}{#1}%
\@tempdimb=\pgf@y
\pgfmathparse{\@tempdimb/\@tempdima}%
\num{\pgfmathresult}%
}}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw [help lines] (0,0) grid [step=1] (2,4);
\draw [name path=A] (0,0) -- (2,4);
\draw [name path=B] (2,0) -- (0,4);
\draw [name intersections={of=A and B}]
(intersection-1)
node [right] {(\xcoord{intersection-1},\ycoord{intersection-1})}
circle (2pt);
\end{tikzpicture}
\end{document}
答案1
PGF的\pgfmathprintnumber
宏使您可以打印和格式,包括四舍五入到十进制数字\pgfmathprintnumber[precision=2]{\pgfmathresult}
。
单位向量存储在\pgf@xx
(x 单位向量的 x 分量)和\pgf@yy
(y 单位向量的 y 分量)中。因此,您的函数可以缩短为
\makeatletter
\newcommand\xcoord[2][center]{{%
\pgfpointanchor{#2}{#1}%
\pgfmathparse{\pgf@x/\pgf@xx}%
\pgfmathprintnumber{\pgfmathresult}%
}}
\newcommand\ycoord[2][center]{{%
\pgfpointanchor{#2}{#1}%
\pgfmathparse{\pgf@y/\pgf@yy}%
\pgfmathprintnumber{\pgfmathresult}%
}}
\makeatother
答案2
这是从节点或锚点中提取坐标值的另一种方法。
\makeatletter
\def\extractcoord#1#2#3{
\path let \p1=(#3) in \pgfextra{
\pgfmathsetmacro#1{\x{1}/\pgf@xx}
\pgfmathsetmacro#2{\y{1}/\pgf@yy}
\xdef#1{#1} \xdef#2{#2}
};
}
\makeatother
例子:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\def\extractcoord#1#2#3{
\path let \p1=(#3) in \pgfextra{
\pgfmathsetmacro#1{\x{1}/\pgf@xx}
\pgfmathsetmacro#2{\y{1}/\pgf@yy}
\xdef#1{#1} \xdef#2{#2}
};
}
\makeatother
\pagestyle{empty}
\begin{document}
\begin{tikzpicture}
\draw[help lines] (0,0) grid (3,4);
\begin{scope}[shift={(1,1)}]
\coordinate (A) at (0,0);
\coordinate (B) at (2,3) ;
\coordinate (C) at ($(A)!.5!(B)$);
\fill[red] (A) circle(2pt);
\fill[red] (B) circle(2pt);
\fill[blue] (C) circle(2pt);
\extractcoord\x\y{C}
\end{scope}
\extractcoord\xb\yb{C}
\end{tikzpicture}
Inner scope: $(\x,\y)$\par
Global scope: $(\xb,\yb)$\par
Inner scope (fixed precision):
$(\pgfmathprintnumber[precision=2]{\x},\pgfmathprintnumber[precision=2]{\y})$\par
\end{document}
答案3
将尺寸划分为1cm
标量将使您以厘米为单位的数字值与Tikz的\let
坐标构造(需要加载Tikz的calc
库),可以简化您的示例,如下所示。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,intersections}
\begin{document}
\begin{tikzpicture}
\draw [help lines] (0,0) grid [step=1] (2,4);
\draw [name path=A] (0,0) -- (2,4);
\draw [name path=B] (2,0) -- (0,4);
\draw [name intersections={of=A and B}]
let
\p1=(intersection-1),
\n1={scalar(\x1/1cm)},
\n2={scalar(\y1/1cm)}
in
(\p1)
node [right] {(\n1,\n2)}
circle (2pt);
\end{tikzpicture}
\end{document}
上述代码没有明确格式化打印的数字。这是一个带格式的版本。
以下命令将(包的)\scalar
可以处理的数学表达式作为强制参数,并去除其维度(如果有),返回纯数值。然后,它使用(包的) 格式化该值,并将其选项设置为的可选参数。\pgfmathparse
pgfmath
\pgfmathprintnumber
pgf
\scalar
\newcommand{\scalar}[2][]{%
\pgfmathscalar{#2}%
\pgfmathprintnumber[#1]{\pgfmathresult}%
}
例如,以下命令的名称\logv
是“逻辑值”的缩写,即出现在您的帖子标题中的表达式,接受维度,并以厘米(Tikz的默认单元)返回其数值,以返回2个小数点位置。
\newcommand{\logv}[1]{\scalar[precision=2,fixed zerofill]{#1/1cm}}
使用这些工具,并记住tikz
包会自动加载pgf
和pgfmath
包,上面的答案可以重写如下。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,intersections}
\newcommand{\scalar}[2][]{%
\pgfmathscalar{#2}%
\pgfmathprintnumber[#1]{\pgfmathresult}%
}
\newcommand{\logv}[1]{\scalar[precision=2,fixed zerofill]{#1/1cm}}
\begin{document}
\begin{tikzpicture}
\draw [help lines] (0,0) grid [step=1] (2,4);
\draw [name path=A] (0,0) -- (2,4);
\draw [name path=B] (2,0) -- (0,4);
\draw [name intersections={of=A and B}]
let \p1=(intersection-1) in
(\p1)
node [right] {(\logv{\x1},\logv{\y1})}
circle (2pt);
\end{tikzpicture}
\end{document}