如何使用 tikz-pgf 进行非线性变换?

如何使用 tikz-pgf 进行非线性变换?

考虑以下 (-2, -1) -- (3, 9) 线段的图:

normal xy-axis

我想要应用一个变换,使得水平轴是某个点的极角,而垂直轴是该点与原点之间的距离。

它看起来应该是这样的:

transformation

我看过了这个问题所以我相信这应该是可能的,但我不太了解里面的代码\def\polartransformation

pgfmath任何关于如何执行此操作的提示或有关这些功能的文档链接都pgftransformnonlinear将不胜感激。

答案1

首先,我认为 pgfmanual 并不完全正确。手册第 107.4.2 节指出

% \pgf@x will contain the radius angle
% \pgf@y will contain the distance
\pgfmathsincos@{\pgf@sys@tonumber\pgf@x}%
% pgfmathresultx is now the cosine of radius angle and 
% pgfmathresulty is the sine of radius angle 
\pgf@x=\pgfmathresultx\pgf@y% 
\pgf@y=\pgfmathresulty\pgf@y%

pgfmanual 中的代码可能正在做的是以xpt 表示坐标,然后取 cos 和 sin x/pt(即,如果 x=50pt,则它将返回 cos(50)),并将结果乘以坐标y,即

(x_new,y_new)=(y_old cos(x_old/pt),y_old sin(x_old/pt))

这导致了代码:

\documentclass{article}
\usepackage{tikz}
\usepgfmodule{nonlineartransformations}
\tikzset{declare function={mymod(\x)=\x-int(\x);}}
\makeatletter
\def\slowtransformation{% modified version of the manual 103.4.2 Installing Nonlinear Transformation
\typeout{before:\space\the\pgf@x\space\the\pgf@y}%
\edef\oriX{\the\pgf@x}%
\edef\oriY{\the\pgf@y}%
\pgfmathsetmacro{\myAngle}{mod(360+atan2(\oriY,\oriX),360)}
\pgfmathsetmacro{\myRadius}{veclen(\oriX,\oriY)}
\typeout{original\space x=\oriX\space y=\oriY}
\typeout{radius=\myRadius\space angle=\myAngle}
\setlength{\pgf@x}{\myAngle pt}
\setlength{\pgf@y}{\myRadius pt}
} 
\def\fastertransformation{% modified version of the manual 103.4.2 Installing Nonlinear Transformation
\pgfmathsetmacro{\myAngle}{mod(720+atan2(\pgf@y,\pgf@x),360)}
\pgfmathsetmacro{\myRadius}{veclen(\pgf@x,\pgf@y)}
\setlength{\pgf@x}{\myAngle pt}
\setlength{\pgf@y}{\myRadius pt}
} 
\makeatother
\begin{document}
\begin{tikzpicture}
\draw[-latex] (-2.3,-2) -- (3.5,-2) node[below]{$x$};
\draw[-latex] (0,-2.3) -- (0,4.5) node[left]{$y$};
\draw[blue]  (-2, -1) -- (3, 4);
\end{tikzpicture}\\
\begin{tikzpicture}
\draw[-latex] (-0.3,0) -- (7.5,0) node[below]{$\varphi$};
\draw[-latex] (0,-0.3) -- (0,4.5) node[left]{$r$};
\pgftransformnonlinear{\slowtransformation}
\draw[blue]  (-2, -1) -- (3, 4);
\end{tikzpicture}
\begin{tikzpicture}
\draw[-latex] (-0.3,0) -- (7.5,0) node[below]{$\varphi$};
\draw[-latex] (0,-0.3) -- (0,4.5) node[left]{$r$};
\pgftransformnonlinear{\fastertransformation}
\draw[blue]  (-2, -1) -- (3, 4);
\end{tikzpicture}
\end{document}

enter image description here

有两个相同的转换,第一个转换(\slowtransformation)更明确,并且问题\typeout更容易理解,而第二个转换(\fastertransformation)则更快一些。

笔记

  • 必须谨慎使用诸如scale=...和 之类的选项。毕竟,这种变换将采用坐标scale和 等变换,并且然后将它们映射到极坐标。因此,如果有人[yscale=0.5]在原点周围画一个圆,那么坐标就是椭圆的坐标,那么变换不是将它们映射到一条水平线(无需任何额外的变换即可完成)。

  • 当前代码将产生 0 到 360 度之间的角度,这由 控制mod(360+atan2(\oriY,\oriX),360)。如果您使用不同的约定,则需要相应地调整这段代码。

更新atan2(y,x):修复了角度( vs )计算中的两个愚蠢错误,atan2(x,y)并使轴标签更加合适。我还删除了所有scale指令并添加了更多解释。

相关内容