我正在使用形式为(-n 激活)非线性变换
x \mapsto (x + a * sin x), y \mapsto y
问题在于x = nπ
,对于整数 n , 的点应该是变换的固定点,因为sin(nπ) = 0
。将变换应用于以下对象似乎显示出与此推理预期的偏差。
变换应用于网格和函数y = f(x) = x
而另一个相同的网格和函数则省略变换以供比较。代码和结果如下。我请你看一下预期相交的点。这似乎没有发生。第二张图片是从红线和蓝线的最后一个相交点拍摄的。
这是数值精度的限制吗?我该如何改进?
\documentclass[tikz,border=3mm]{standalone}
\usepgfmodule{nonlineartransformations}
\makeatletter
\def\mytransformation{%
\pgfmathsetmacro{\myX}{\pgf@x + (10)*sin(\pgf@x) }
\pgfmathsetmacro{\myY}{\pgf@y}
\setlength{\pgf@x}{\myX pt}
\setlength{\pgf@y}{\myY pt}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\begin{scope}
\pgftransformnonlinear{\mytransformation}
\draw [red] (0,0) grid [xstep=.5*pi, ystep=-1] (23,23);
\draw [red, thick] (0,0) -- (20,20);
\end{scope}
\draw [blue, dashed,] (0,0) grid [step=.5*pi] (23,23);
\draw [blue, thick] (0,0) -- (20,20);
\end{tikzpicture}
\end{document}
答案1
让我们分解一下:
PGFmath 假设 sin、cos 等参数以度为单位,而不是弧度,因此我们需要使用
deg
或r
后缀运算符进行转换:sin(deg(X)或 sin(X r)。TikZ/PGF/TeX 内部与 pt 一起工作,其中1 厘米 = 28.45274 点。因此,即使我们将弧度转换为度数,结果也是完全错误的。
TikZ/PGF 用途各种坐标系. 最重要的是
canvas
我们使用实际长度的坐标系:(10mm, -3em)
- 这
xyz
系(尽管我们经常只使用X和是) 其中我们使用标量值:(2, 2*pi+3/2)
。
这两个坐标系都有极坐标版本
(<angle>:<value>)
,但可以转换为X和是轻松获取价值。坐标系如何
xyz
知道一个值的长度,例如2
或2*pi+3/2
在纸上有多长?它使用另一个转换层和赋予键的值x
,y
以及z
。默认情况下,它们是x = 1cm
(表示画布上向右方向 1 厘米)和y = 1m
(向上)。这是PGF 在其层上提供。
那么我们除以\pgf@x
并将1cm
其转换为度数就完成了吗?
1cm
不完全是。首先,我们可以通过使用\pgf@xx
除以来访问的值\pgf@x
,但这样我们就在坐标系中了。我们需要通过将正弦乘以来xyz
返回坐标系,这将带我得到你应该想要使用的这个公式:canvas
\pgf@xx
\def\mytransformation{%
\pgfmathsetlength\pgf@x{\pgf@x + 10*\pgf@xx*sin(\pgf@x/\pgf@xx r)}%
}
也就是说,转换画布X值返回到其 xyzX值,将其转换为度数,取其正弦值,然后将其乘回到画布坐标系(然后乘以 10 的因子)。
现在,如果你使用更复杂的xyz
坐标系,我们就说x = {(1cm, 1cm)}
,即X轴在纸面上呈45°角,长度均为√2
\pgf@xx
(单位的长度X轴入X方向)和\pgf@xy
(单位的长度X轴入是方向)
将设置为 28.45274pt。
(是的,还有\pgf@yy
、\pgf@yx
和\pgf@zx
。\pgf@zy
)
我不知道你的转变会是什么样子。(那时候,我相信这是一个数学问题。)
如果你查看手册中的例子非线性变换你会注意到它只使用canvas
坐标系中的坐标。该\polartransformation
示例甚至使用
\draw (0pt,0mm) grid [xstep=10pt, ystep=5mm] (90pt, 20mm);
注意90pt
!对于它要绘制的四分之一圆,这将是 90°。(或者 3.16314cm,即(3.16314, 2)
在坐标系中xyz
。有点接近 π,但纯属偶然——无论如何我们都在寻找 π/2。)
我已经添加了阴谋
\draw[dashed, ultra thick] plot[smooth,samples=100,domain=0:20] ({\x + 10 * sin(\x r)}, \x);
以供比较。根据您的实际任务,这可能只是一种绘制符合任何(?)变换的线条的更简单方法。
如果你真的想绘制一些东西,可以使用pgf图。
代码
\documentclass[tikz,border=3mm]{standalone}
\usepgfmodule{nonlineartransformations}
\makeatletter
\def\mytransformation{%
\pgfmathsetlength\pgf@x{\pgf@x + 10*\pgf@xx*sin(\pgf@x/\pgf@xx r)}%
}
\makeatother
\begin{document}
\begin{tikzpicture}[x=.5cm]% for fun
\foreach \x in {-3,...,10}
\path (0:\x*pi) node[below]{$\x\pi$} edge[help lines, very thin] + (up:20) edge + (up:2pt)
++ (0:.5*pi) node[below]{$\pgfmathprint{\x+.5}\pi$} edge[help lines, very thin, dotted] + (up:20) edge + (up:1pt);
\draw[dashed, ultra thick] plot[smooth,samples=100,domain=0:20] ({\x + 10 * sin(\x r)}, \x);
\foreach \sh in {-10,0,10}
\draw[shift=(0:\sh)] (0,0) -- (20,20);
\begin{scope}
\pgftransformnonlinear{\mytransformation}
\draw [thick, red] (0,0) -- (20,20);
\end{scope}
\end{tikzpicture}
\end{document}