如何在弧线上做标记(tikz,装饰)

如何在弧线上做标记(tikz,装饰)

我对这段代码有疑问:

\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} 

在此处输入图片描述

相关内容