使用 Lua 而不是 xfp 的问题

使用 Lua 而不是 xfp 的问题

初始代码如下:想法是通过临时修改宏来避免“维度太大”的veclen错误

\documentclass{standalone} 
\usepackage{tkz-euclide}

\begin{document} 
%  Schrodinger's cat idea 03/01/20
\makeatletter
\tikzset{xfp/.code={%
\pgfmathdeclarefunction*{veclen}{2}{%
\begingroup%
    \pgfmath@x##1pt\relax%
    \pgfmath@y##2pt\relax%
    \edef\tkz@xfpMathLen{\fpeval{sqrt((\pgf@x)^2+(\pgf@y)^2)}}   
    \pgfmath@returnone\tkz@xfpMathLen pt%
\endgroup%
}}}%
\makeatother
 
\begin{tikzpicture}[scale=1]
  \tkzDefPoint(0,0){O}
  \tkzDefPoint(2.5,0){N}
  \tkzDefPoint(-4.2,0.5){M}
  \tkzDefPointBy[rotation=center O angle 30](N)
  \tkzGetPoint{B}
  \tkzDefPointBy[rotation=center O angle -50](N)
  \tkzGetPoint{A}
  \tkzInterLC[common=B](M,B)(O,B) \tkzGetFirstPoint{C}
  \tkzInterLC[common=A](M,A)(O,A) \tkzGetFirstPoint{A'}
  \tkzDrawSegments(A,C M,A M,B A,B)
  \tkzDrawCircle(O,N)
% \tkzMarkAngle[mkpos=.2, size=1.2](C,A,M) 
% Latex Error: ./testlua2.tex:32 Dimension too large.
  \begin{scope}[xfp]
    \tkzMarkAngle[mkpos=.2, size=1.2](C,A,M)
  \end{scope}
  \tkzDrawPoints(O, A, B, M, B, C, A')
  \tkzLabelPoints[right](O,A,B)
  \tkzLabelPoints[above left](M,C)
  \tkzLabelPoint[below left](A'){$A'$}
\end{tikzpicture}
\end{document}

在此处输入图片描述

现在我尝试lua这样使用:

\documentclass{standalone} 
\usepackage{tkz-euclide}

\begin{document} 
%  Schrodinger's cat idea 03/01/20
\makeatletter
\tikzset{lua/.code={%
\pgfmathdeclarefunction*{veclen}{2}{%
\begingroup%
 \pgfmath@x##1pt\relax%
 \pgfmath@y##2pt\relax%
 \pgf@xa=\pgf@x%
 \pgf@ya=\pgf@y%
 \edef\tkz@temp@xa{\pgfmath@tonumber{\pgf@xa}}% \strip@pt ??
 \edef\tkz@temp@ya{\pgfmath@tonumber{\pgf@ya}}%
 \edef\tkz@xfpMathLen{\directlua{tex.print(math.sqrt((\tkz@temp@xa)^2+(\tkz@temp@ya)^2))}}
% \edef\tkz@xfpMathLen{\fpeval{round(\tkz@xfpMathLen,6)}} % with this line I get a result
\pgfmath@returnone\tkz@xfpMathLen pt%
\endgroup%
 }}}%
 \makeatother
 
\begin{tikzpicture}[scale=1]
  \tkzDefPoint(0,0){O}
  \tkzDefPoint(2.5,0){N}
  \tkzDefPoint(-4.2,0.5){M}
  \tkzDefPointBy[rotation=center O angle 30](N)
  \tkzGetPoint{B}
  \tkzDefPointBy[rotation=center O angle -50](N)
  \tkzGetPoint{A}
  \tkzInterLC[common=B](M,B)(O,B) \tkzGetFirstPoint{C}
  \tkzInterLC[common=A](M,A)(O,A) \tkzGetFirstPoint{A'}
  \tkzDrawSegments(A,C M,A M,B A,B)
  \tkzDrawCircle(O,N)
% \tkzMarkAngle[mkpos=.2, size=1.2](C,A,M) 
% Latex Error: ./testlua2.tex:32 Dimension too large.
  \begin{scope}[lua]
    \tkzMarkAngle[mkpos=.2, size=1.2](C,A,M)
  \end{scope}
  \tkzDrawPoints(O, A, B, M, B, C, A')
  \tkzLabelPoints[right](O,A,B)
  \tkzLabelPoints[above left](M,C)
  \tkzLabelPoint[below left](A'){$A'$}
\end{tikzpicture}
\end{document}

但我收到以下错误:!非法测量单位(pt 插入)。如果我使用以下方法,此错误会消失:

\edef\tkz@xfpMathLen{\fpeval{round(\tkz@xfpMathLen,6)}}

我必须承认我不明白发生了什么。如何正确避免这个错误?

为了将尺寸转换为数字,我知道两种方法:\pgfmath@tonumber \strip@pt。我都试过了,但没有成功。我不知道这是否是问题所在。

答案1

其中一项计算返回9.4868329805051e-05

你必须告诉 Lua 始终返回非指数形式的数字(我相信有办法)。

与此同时

\edef\tkz@xfpMathLen{\fpeval{\directlua{tex.print(math.sqrt((\tkz@temp@xa)^2+(\tkz@temp@ya)^2))}}}

解决了该问题,因为它\fpeval使输出标准化。

在此处输入图片描述

可能更好的方法是定义一个“毕达哥拉斯加法”的宏:

\documentclass[border=4]{standalone} 
\usepackage{tkz-euclide}
\usepackage{iftex}

\begin{document} 
%  Schrodinger's cat idea 03/01/20
\makeatletter

\ifluatex
\newcommand{\tkz@pythadd}[2]{%
  \directlua{%
    tex.print(string.format('\@percentchar.12f',math.sqrt((#1)^2+(#2)^2)))%
  }%
}
\else
\newcommand{\tkz@pythadd}[2]{%
  \fpeval{(#1)^2+(#2)^2}%
}
\fi


\tikzset{lua/.code={%
\pgfmathdeclarefunction*{veclen}{2}{%
\begingroup%
 \pgfmath@x##1pt\relax%
 \pgfmath@y##2pt\relax%
 \pgf@xa=\pgf@x%
 \pgf@ya=\pgf@y%
 \edef\tkz@temp@xa{\pgfmath@tonumber{\pgf@xa}}% \strip@pt ??
 \edef\tkz@temp@ya{\pgfmath@tonumber{\pgf@ya}}%
 \edef\tkz@xfpMathLen{\tkz@pythadd{\tkz@temp@xa}{\tkz@temp@ya}}%
% \edef\tkz@xfpMathLen{\fpeval{round(\tkz@xfpMathLen,6)}} % with this line I get a result
\pgfmath@returnone\tkz@xfpMathLen pt%
\endgroup%
 }}}%
 \makeatother
 
\begin{tikzpicture}[scale=1]
  \tkzDefPoint(0,0){O}
  \tkzDefPoint(2.5,0){N}
  \tkzDefPoint(-4.2,0.5){M}
  \tkzDefPointBy[rotation=center O angle 30](N)
  \tkzGetPoint{B}
  \tkzDefPointBy[rotation=center O angle -50](N)
  \tkzGetPoint{A}
  \tkzInterLC[common=B](M,B)(O,B) \tkzGetFirstPoint{C}
  \tkzInterLC[common=A](M,A)(O,A) \tkzGetFirstPoint{A'}
  \tkzDrawSegments(A,C M,A M,B A,B)
  \tkzDrawCircle(O,N)
% \tkzMarkAngle[mkpos=.2, size=1.2](C,A,M) 
% Latex Error: ./testlua2.tex:32 Dimension too large.
  \begin{scope}[lua]
    \tkzMarkAngle[mkpos=.2, size=1.2](C,A,M)
  \end{scope}
  \tkzDrawPoints(O, A, B, M, B, C, A')
  \tkzLabelPoints[right](O,A,B)
  \tkzLabelPoints[above left](M,C)
  \tkzLabelPoint[below left](A'){$A'$}
\end{tikzpicture}
\end{document}

答案2

以下是对已提出的不同想法的简要总结

A)egreg 找到了问题的根源,并根据我的解决方法找到了解决方案

\edef\tkz@xfpMathLen{\fpeval{\directlua{tex.print(math.sqrt((\tkz@temp@xa)^2+(\tkz@temp@ya)^2))}}}

B)包装函数是来自 user202729 的一个好主意

 \RequirePackage{luacode}

 \begin{luacode}
   function print_decimal(num)
      return tex.print(string.format("\csstring\%f", num))
   end
 \end{luacode}

然后

\tikzset{lua/.code={%
 \pgfmathdeclarefunction*{veclen}{2}{%
 \begingroup%
  \pgfmath@x##1pt\relax%
  \pgfmath@y##2pt\relax%
  \pgf@xa=\pgf@x%
  \pgf@ya=\pgf@y%
  \edef\tkz@temp@xa{\pgfmath@tonumber{\pgf@xa}}% \strip@pt ??
  \edef\tkz@temp@ya{\pgfmath@tonumber{\pgf@ya}}%
  \edef\tkz@tmp{math.sqrt((\tkz@temp@xa)^2+(\tkz@temp@ya)^2)}
  \edef\tkz@xfpMathLen{\directlua{print_decimal(\tkz@tmp)}}
  \pgfmath@returnone\tkz@xfpMathLen pt%
\endgroup%
}}}%

\begin{scope}[lua]
     \tkzMarkAngle[mkpos=.2, size=1.2](C,A,M)
 \end{scope}

C)将指数形式的数字转换为十进制形式的数字有几种方法。Ulrike
Fischer 提出

tex.print(string.format('\@percentchar.12f',math.sqrt(...

我向 Henri Menke 提出了一个想法

   tex.print(string.format("\csstring\%f",...))

这是 !

相关内容