Pgfmath 数值四元数乘法用于 3D 旋转

Pgfmath 数值四元数乘法用于 3D 旋转

我需要将 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}

相关内容