我需要将 3D 空间中的坐标围绕给定轴旋转某个已知角度,以便在 tikz 中绘制立体图形。一种方法是计算乘积点阵图-1, 在哪里页是一个四元数,定义为, 和问是要旋转的点:. 对于旋转,我们可以得到磷-1只需翻转 p 的虚部的符号,即
该产品由宏计算
\newcommand{\quaternionproduct}[2] {
\pgfmathparse{{#1}[0]*{#2}[0] - {#1}[1]*{#2}[1] - {#1}[2]*{#2}[2] - {#1}[3]*{#2}[3]}\pgfmathresult,
\pgfmathparse{{#1}[0]*{#2}[1] + {#1}[1]*{#2}[0] + {#1}[2]*{#2}[3] - {#1}[3]*{#2}[2]}\pgfmathresult,
\pgfmathparse{{#1}[0]*{#2}[2] - {#1}[1]*{#2}[3] + {#1}[2]*{#2}[0] + {#1}[3]*{#2}[1]}\pgfmathresult,
\pgfmathparse{{#1}[0]*{#2}[3] + {#1}[1]*{#2}[2] - {#1}[2]*{#2}[1] + {#1}[3]*{#2}[0]}\pgfmathresult
}
根据乘积规则,它应该返回另一个四元数(https://en.wikipedia.org/wiki/Quaternion#Hamilton_product),并且它确实:
\def\angle{30}
\pgfmathsetmacro{\r}{cos(\angle/2) }
\pgfmathsetmacro{\x}{sin(\angle/2)* 2/7}
\pgfmathsetmacro{\y}{sin(\angle/2)* 3/7}
\pgfmathsetmacro{\z}{sin(\angle/2)* 6/7}
\def\myquatP {\r, \x, \y, \z} % Rotates 30° about the unit vector (2/7, 3/7, 6/7)
\def\myquatInvP{\r, -\x, -\y, -\z} % = P^-1
\def\myquatQ{\quaternionfromxyz{1, 1, 1}} % A point to rotate
\def\myquatTmp{\quaternionproduct{\myquatP}{\myquatQ}}\myquatTmp % This prints the correct result
但是,当我继续计算时,如果我尝试重用新计算的结果,则编译将失败并出现错误 ! Incomplete \iffalse; all text was ignored after line 38
。
\def\myquatQrot{\quaternionproduct{\myquatTmp}{\myquatInvP}}\myquatQrot % Not working
如何生成在 tikz 中使用的旋转坐标?我希望我可以做类似的事情:
\newcommand{\rotate}[2]{
\quaterniontoxyz{
\quaternionproduct{
#1 % First argument is P, the rotation
}{
\quaternionproduct{ % This is a nested products
\quaternionfromxyz(#2)
}{
\quaternioninvert{#1} % Inverts P
}
}
} % Conversion to x,y,z
} % End newcommand
\begin{tikzpicture}
\draw[] (\rotate{\myquatP}{1, 1, 1}) -- (\rotate{\myquatP}{0, 0, 0});
% ...
\end{tikzpicture}
这是 MWE
\documentclass[11pt]{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\newcommand{\quaternionfromxyz}[1] {0, #1}
\newcommand{\quaterniontoxyz}[1] {
\pgfmathparse{{#1}[1]}\pgfmathresult,
\pgfmathparse{{#1}[2]}\pgfmathresult,
\pgfmathparse{{#1}[3]}\pgfmathresult}
\newcommand{\quaternionproduct}[2] {
\pgfmathparse{{#1}[0]*{#2}[0] - {#1}[1]*{#2}[1] - {#1}[2]*{#2}[2] - {#1}[3]*{#2}[3]}\pgfmathresult,
\pgfmathparse{{#1}[0]*{#2}[1] + {#1}[1]*{#2}[0] + {#1}[2]*{#2}[3] - {#1}[3]*{#2}[2]}\pgfmathresult,
\pgfmathparse{{#1}[0]*{#2}[2] - {#1}[1]*{#2}[3] + {#1}[2]*{#2}[0] + {#1}[3]*{#2}[1]}\pgfmathresult,
\pgfmathparse{{#1}[0]*{#2}[3] + {#1}[1]*{#2}[2] - {#1}[2]*{#2}[1] + {#1}[3]*{#2}[0]}\pgfmathresult
}
\begin{document}
\def\angle{30}
\pgfmathsetmacro{\r}{cos(\angle/2) }
\pgfmathsetmacro{\x}{sin(\angle/2)* 2/7}
\pgfmathsetmacro{\y}{sin(\angle/2)* 3/7}
\pgfmathsetmacro{\z}{sin(\angle/2)* 6/7}
\def\myquatP {\r, \x, \y, \z} % Rotates 30° about the unit vector (2/7, 3/7, 6/7)
\def\myquatInvP{\r, -\x, -\y, -\z} % = P^-1
\myquatP
\myquatInvP
% A test to check whether the product function works (and it does)
\quaternionproduct{\myquatP}{\myquatInvP} % This should be (1, 0, 0, 0)
\def\myquatQ{\quaternionfromxyz{1, 1, 1}} % A point to rotate
\def\myquatTmp{\quaternionproduct{\myquatP}{\myquatQ}}\myquatTmp % This works
\def\myquatQrot{\quaternionproduct{\myquatTmp}{\myquatInvP}}\myquatQrot % This does not
% \myquatQrot should be in the form (0, x, y, z)
\begin{tikzpicture}
% [...] Draws the rotated points
\end{tikzpicture}
\end{document}