我对这段代码有疑问:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\begin{document}
\begin{tikzpicture}[decoration={markings, mark = at position .5 with
{\draw (-2pt,-2pt) -- (2pt,2pt) (2pt,-2pt) -- (-2pt,2pt);}}]
% wrong
%\draw [postaction={decorate}] (0,0) -- ++(146:1) arc (146:157:1)--(0,0);
%fine
\draw [postaction={decorate}] (0,0) -- ++(146:1.2) arc (146:157:1.2)--(0,0);
\end{tikzpicture}
\end{document}
% 错误后面的行给出了错误dimension too large
。我认为这是一个数学问题,因为圆弧或半径太小,或者两者都有。一个解决方案是(另一个是使用比例> 1,但对于细线不要使用像 .8 这样的比例):
\documentclass{article}
\usepackage{tikz,fp}
\usetikzlibrary{decorations.markings,fixedpointarithmetic}
\begin{document}
\begin{tikzpicture}[fixed point arithmetic,
decoration={markings, mark = at position .5 with
{\draw (-2pt,-2pt) -- (2pt,2pt) (2pt,-2pt) -- (-2pt,2pt);}}]
\draw [postaction={decorate}] (0,0) -- ++(146:1) arc (146:157:1)--(0,0);
\end{tikzpicture}
\end{document}
但是我无法使用它,因为编译时间太长。
是否有可能加快最后一段代码的速度,或者也许有人知道另一种方法可以不出错地获得标记?也许我用decoration
错了方法!
答案1
问题在于数学函数的实现veclen
。简而言之,它没有做就是了(x^2 + y^2)^{1/2}
(怎么可能?开平方根根本不可能理论上更不用说精度问题了。)但会做一些更复杂的事情,在某个阶段涉及到分割其中一个组件。您可以通过以下简单的方法测试:
\pgfmathparse{veclen(0.00006,0.00006)}
(选择这个数字是因为发生是 TeX 在尝试 Altermundus 的示例时出错的数字。乘以 10,一切又恢复正常。)
查看实现时,veclen
我注意到它进行了一些初始缩放以考虑大数字。所以我添加了一些行来测试小数字。这似乎解决了问题。
(不幸的是,我无法正常\pgfmathredeclarefunction
工作。我没有调试它,而是只使用\let
旧函数\relax
并覆盖它。)
代码:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\makeatletter
\let\pgfmath@function@veclen\relax
\pgfmathdeclarefunction{veclen}{2}{%
\begingroup%
\pgfmath@x#1pt\relax%
\pgfmath@y#2pt\relax%
\ifdim\pgfmath@x<0pt\relax%
\pgfmath@x-\pgfmath@x%
\fi%
\ifdim\pgfmath@y<0pt\relax%
\pgfmath@y-\pgfmath@y%
\fi%
\ifdim\pgfmath@x=0pt\relax%
\pgfmath@x\pgfmath@y%
\else%
\ifdim\pgfmath@y=0pt\relax%
\else%
\ifdim\pgfmath@x>\pgfmath@y%
\pgfmath@xa\pgfmath@x%
\pgfmath@x\pgfmath@y%
\pgfmath@y\pgfmath@xa%
\fi%
% We use a scaling factor to reduce errors.
% First, see if we should scale down
\let\pgfmath@tmp@scale=\divide
\let\pgfmath@tmp@restore=\multiply
\ifdim\pgfmath@y>10000pt\relax%
\c@pgfmath@counta1500\relax%
\else%
\ifdim\pgfmath@y>1000pt\relax%
\c@pgfmath@counta150\relax%
\else%
\ifdim\pgfmath@y>100pt\relax%
\c@pgfmath@counta50\relax%
\else%
% Not scaling down, should we scale up?
\let\pgfmath@tmp@scale=\multiply
\let\pgfmath@tmp@restore=\divide
\ifdim\pgfmath@y<0.00001pt\relax%
\c@pgfmath@counta1500\relax%
\else%
\ifdim\pgfmath@y<0.0001pt\relax%
\c@pgfmath@counta150\relax%
\else%
\ifdim\pgfmath@y<0.001pt\relax%
\c@pgfmath@counta50\relax%
\else
\c@pgfmath@counta1\relax%
\fi%
\fi%
\fi%
\fi%
\fi%
\fi%
\pgfmath@tmp@scale\pgfmath@x\c@pgfmath@counta\relax%
\pgfmath@tmp@scale\pgfmath@y\c@pgfmath@counta\relax%
\pgfmathreciprocal@{\pgfmath@tonumber{\pgfmath@y}}%
\pgfmath@x\pgfmathresult\pgfmath@x%
\pgfmath@xa\pgfmath@tonumber{\pgfmath@x}\pgfmath@x%
\edef\pgfmath@temp{\pgfmath@tonumber{\pgfmath@xa}}%
%
% Use A+x^2*(B+x^2*(C+x^2*(D+E*x^2)))
% where
% A = +1.000012594
% B = +0.4993615349
% C = -0.1195159052
% D = +0.04453994279
% E = -0.01019210944
%
\[email protected]\pgfmath@xa%
\advance\[email protected]\relax%
\pgfmath@x\pgfmath@temp\pgfmath@x%
\advance\[email protected]\relax%
\pgfmath@x\pgfmath@temp\pgfmath@x%
\advance\[email protected]\relax%
\pgfmath@x\pgfmath@temp\pgfmath@x%
\advance\[email protected]\relax%
\ifdim\pgfmath@y<0pt\relax%
\pgfmath@y-\pgfmath@y%
\fi%
\pgfmath@x\pgfmath@tonumber{\pgfmath@y}\pgfmath@x%
% Invert the scaling factor.
\pgfmath@tmp@restore\pgfmath@x\c@pgfmath@counta\relax%
\fi%
\fi%
\pgfmath@returnone\pgfmath@x%
\endgroup%
}
\makeatother
\begin{document}
\pgfmathparse{veclen(0.00006,0.00005)}
Vector length is: \pgfmathresult
\begin{tikzpicture}[decoration={markings, mark = at position .5 with
{\draw (-2pt,-2pt) -- (2pt,2pt) (2pt,-2pt) -- (-2pt,2pt);}}]
% wrong
\draw [postaction={decorate}] (0,0) -- ++(146:1) arc (146:157:1) -- (0,0);
%fine
\draw [postaction={decorate}] (2,0) -- ++(146:1.2) arc (146:157:1.2) -- (2,0);
\end{tikzpicture}
\end{document}
结果:
可以看出,准确度并不高!但是,在这种精度水平下,准确度可能并不那么重要。也许更好的实现是测试向量的分量是否小于某个小数,然后简单地返回两者中的最大值:在这种水平下,sup 范数和 l^2 范数之间的差异并不大!(稍微复杂一点的版本会有一个开关,根据低估或高估是否可以接受,返回 sup 范数或 l^1 范数。)
答案2
我回答我的问题是因为也许它对某些人有用。这是我的第一个宏,所以lualatex
也许我做了一些非常糟糕的事情。我不知道如何确切地得到结果luaveclen
,也许tostring
没有必要。编译时间是正确的!
%!TEX TS-program = lualatex
\documentclass[11pt]{article}
\usepackage{fontspec}
\usepackage{luatextra}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\begin{document}
\makeatletter
\def\luaveclen#1#2{
\directlua{
x = #1;
y = #2;
r=(x*x+y*y)^0.5
tex.print(tostring(r))}
}
\pgfmathdeclarefunction*{veclen}{2}{%
\begingroup
\edef\pgfmath@tmp{\luaveclen{#1}{#2}}
\pgfmath@returnone\pgfmath@tmp pt
\endgroup
}
\makeatother
\pgfmathparse{veclen(0.00003,0.00004)}
Vector length is: \pgfmathresult
\begin{tikzpicture}[decoration={markings, mark = at position .5 with
{\draw (-2pt,-2pt) -- (2pt,2pt) (2pt,-2pt) -- (-2pt,2pt);}}]
\draw [postaction={decorate}] (0,0) -- ++(146:1) arc (146:157:1) -- (0,0);
\end{tikzpicture}
\end{document}