初始代码如下:想法是通过临时修改宏来避免“维度太大”的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",...))
这是 !