如何编写一个好的矢量解析器,可以执行 \pgfvecparse{\A=\B-\C; \D=\E x \F;}

如何编写一个好的矢量解析器,可以执行 \pgfvecparse{\A=\B-\C; \D=\E x \F;}

我经常使用点的坐标来绘制几何图形。我知道,我们可以添加、减去点的坐标,例如

\begin{tikzpicture}
\tkzDefPoints{0/0/C',3/0/D',1/1/B'}
\coordinate (A') at ($(B')+(D')-(C')$);
 \end{tikzpicture}

如果我有两个点A(1,2,3)B(4,5,6),我该如何将向量定义AB(\B)-(\A)

答案1

如果仅将坐标用于绘图,则只需将点的每个组成部分定义为变量,然后使用它们定义坐标点。例如:

\documentclass[margin=3.14159mm]{standalone}
\usepackage{tikz,tikz-3dplot}

\begin{document}
\tdplotsetmaincoords{60}{125}
\begin{tikzpicture}
    [scale=0.9,
    tdplot_main_coords,
    axis/.style={-latex,thick},
    vector/.style={-stealth,red,very thick},
    vector guide/.style={dashed,thick}]

%standard tikz coordinate definition using x, y, z coords
% A(2,4,3), B(3,-1,4)
\def\Ax{2}
\def\Ay{4}
\def\Az{3}
\def\Bx{-1}
\def\By{3}
\def\Bz{4}
\coordinate (O) at (0,0,0);
\coordinate (A) at (\Ax,\Ay,\Az);
\coordinate (B) at (\Bx,\By,\Bz);
%draw axes
\draw[axis] (0,0,0) -- (4,0,0) node[anchor=north east]{$x$};
\draw[axis] (0,0,0) -- (0,4,0) node[anchor=north west]{$y$};
\draw[axis] (0,0,0) -- (0,0,5) node[anchor=south]{$z$};
%Dot at point
\fill [blue] (A) circle (2pt);
\fill [blue] (B) circle (2pt);
%draw a vector from O to A and O to B
\draw[vector guide] (O)node[left=1mm]{} -- (A)node[above=-1mm,right]{$P_1(\Ax,\Ay,\Az)$};
\draw[vector guide] (O) -- (B)node[above=-1mm,right]{$P_2(\Bx,\By,\Bz)$};

%draw vector D=AB
\draw[vector] (A) -- (B)node[midway,above,sloped]{$\mathbf{D}$};
\end{tikzpicture}
\end{document}

在此处输入图片描述


补充

在得到回答者的许可后,我(Steven B Segletes)在此展示了如何 listofitems使用该包来简化语法,并可能提供更高的可读性。有了它,我可以通过读取列表来创建数组,语法为\readlist\A{2,4,3}。然后,表达式\A[]将返回数组2,4,3,这足以在当前 MWE 中使用。但是,各个组件也可以作为\A[1]\A[2]和来访问\A[3],可以根据需要用于各种计算。

\documentclass[margin=3.14159mm]{standalone}
\usepackage{tikz,tikz-3dplot,listofitems}

\begin{document}
\tdplotsetmaincoords{60}{125}
\begin{tikzpicture}
    [scale=0.9,
    tdplot_main_coords,
    axis/.style={-latex,thick},
    vector/.style={-stealth,red,very thick},
    vector guide/.style={dashed,thick}]

%standard tikz coordinate definition using x, y, z coords
% A(2,4,3), B(3,-1,4)
\readlist\A{2,4,3}
\readlist\B{-1,3,4}
\coordinate (O) at (0,0,0);
\coordinate (A) at (\A[]);
\coordinate (B) at (\B[]);
%draw axes
\draw[axis] (0,0,0) -- (4,0,0) node[anchor=north east]{$x$};
\draw[axis] (0,0,0) -- (0,4,0) node[anchor=north west]{$y$};
\draw[axis] (0,0,0) -- (0,0,5) node[anchor=south]{$z$};
%Dot at point
\fill [blue] (A) circle (2pt);
\fill [blue] (B) circle (2pt);
%draw a vector from O to A and O to B
\draw[vector guide] (O)node[left=1mm]{} -- (A)node[above=-1mm,right]{$P_1(\A[])$};
\draw[vector guide] (O) -- (B)node[above=-1mm,right]{$P_2(\B[])$};

%draw vector D=AB
\draw[vector] (A) -- (B)node[midway,above,sloped]{$\mathbf{D}$};
\end{tikzpicture}
\end{document}

答案2

只是为了好玩,我编写了 3D 向量加法、减法、叉积和点积(标量视为 1D 向量)的例程。我试图实际解析 \A+\B 形式的表达式,但最终放弃了。

\documentclass{article}
\usepackage{listofitems}
\usepackage{pgfmath}
\usepackage{amsmath}

\makeatletter
\newcommand{\@vecargs}{}% reserve global names

\newcommand{\vecadd}{}
\newcommand{\vecsub}{}
\newcommand{\vecdot}{}
\newcommand{\veccross}{}
\newcommand{\vecparse}{}

\def\vecadd#1#2#3% #1 = #2 + #3
{\bgroup% local definitions
  \pgfmathsetmacro{\@x}{#2[1]+#3[1]}%
  \pgfmathsetmacro{\@y}{#2[2]+#3[2]}%
  \pgfmathsetmacro{\@z}{#2[3]+#3[3]}%
  \xdef\@vecargs{\@x,\@y,\@z}%
\egroup
\readlist#1{\@vecargs}}

\def\vecsub#1#2#3% #1 = #2 - #3
{\bgroup% local definitions
  \pgfmathsetmacro{\@x}{#2[1]-#3[1]}%
  \pgfmathsetmacro{\@y}{#2[2]-#3[2]}%
  \pgfmathsetmacro{\@z}{#2[3]-#3[3]}%
  \xdef\@vecargs{\@x,\@y,\@z}%
\egroup
\readlist#1{\@vecargs}}

\def\vecdot#1#2#3% #1 = #2 \cdot #3
{\pgfmathsetmacro{\@vecargs}{#2[1]*#3[1] + #2[2]*#3[2] + #2[3]*#3[3]}%
\readlist#1{\@vecargs}}

\def\veccross#1#2#3% #1 = #2 \times #3
{\bgroup% local definitions
  \pgfmathsetmacro{\@x}{#2[2]*#3[3] - #2[3]*#3[2]}%
  \pgfmathsetmacro{\@y}{#2[3]*#3[1] - #2[1]*#3[3]}%
  \pgfmathsetmacro{\@z}{#2[1]*#3[2] - #2[2]*#3[1]}%
  \xdef\@vecargs{\@x,\@y,\@z}%
\egroup
\readlist#1{\@vecargs}}
\makeatother

\begin{document}
\readlist\A{1,2,3}
\readlist\B{4,5,6}

\vecadd\C\A\B
\C[]

\vecsub\C\A\B
\C[]

\vecdot\C\A\B
\C[]

\veccross\C\A\B
\C[]
\end{document}

补充

我希望 John 不介意我 (Steven B Segletes) 将他备受追捧的解析器添加到代码中。这样可以输入\vecparse\C{\A+\B}\vecparse\C{\A - \B}\vecparse\C{\A .\B}和形式的内容\vecparse\C{\A x\B}(额外的空格无所谓)。

不仅增加了对 的支持,\vecparse\C{\A x\B}还增加了对和的支持。\vecparse\C{\A x(3,5,6)}\vecparse\C{(3,5,6)x\B}\vecparse\C{(1,1,1)x(1,2,3)}

\documentclass{article}
\usepackage{listofitems}
\usepackage{pgfmath}
\usepackage{amsmath}

\makeatletter
\newcommand{\@vecargs}{}% reserve global names

\newcommand{\vecadd}{}
\newcommand{\vecsub}{}
\newcommand{\vecdot}{}
\newcommand{\veccross}{}
\newcommand{\vecparse}{}

\def\vecadd#1#2#3% #1 = #2 + #3
{\bgroup% local definitions
  \pgfmathsetmacro{\@x}{#2[1]+#3[1]}%
  \pgfmathsetmacro{\@y}{#2[2]+#3[2]}%
  \pgfmathsetmacro{\@z}{#2[3]+#3[3]}%
  \xdef\@vecargs{\@x,\@y,\@z}%
\egroup
\setsepchar{,}%
\readlist#1{\@vecargs}}

\def\vecsub#1#2#3% #1 = #2 - #3
{\bgroup% local definitions
  \pgfmathsetmacro{\@x}{#2[1]-#3[1]}%
  \pgfmathsetmacro{\@y}{#2[2]-#3[2]}%
  \pgfmathsetmacro{\@z}{#2[3]-#3[3]}%
  \xdef\@vecargs{\@x,\@y,\@z}%
\egroup
\setsepchar{,}%
\readlist#1{\@vecargs}}

\def\vecdot#1#2#3% #1 = #2 \cdot #3
{\pgfmathsetmacro{\@vecargs}{#2[1]*#3[1] + #2[2]*#3[2] + #2[3]*#3[3]}%
\setsepchar{,}%
\readlist#1{\@vecargs}}

\def\veccross#1#2#3% #1 = #2 \times #3
{\bgroup% local definitions
  \pgfmathsetmacro{\@x}{#2[2]*#3[3] - #2[3]*#3[2]}%
  \pgfmathsetmacro{\@y}{#2[3]*#3[1] - #2[1]*#3[3]}%
  \pgfmathsetmacro{\@z}{#2[1]*#3[2] - #2[2]*#3[1]}%
  \xdef\@vecargs{\@x,\@y,\@z}%
\egroup
\setsepchar{,}%
\readlist#1{\@vecargs}}

\def\vecparse#1#2{%
  \setsepchar{+||-||x||./(||)}%
  \readlist*\@findop{#2}%
  \ifnum\listlen\@findop[1]=1\relax
    \itemtomacro\@findop[1]\tmpA
  \else
    \itemtomacro\@findop[1,2]\tmpF
    \setsepchar{,}%
    \readlist\tmpE{\tmpF}%
    \def\tmpA{\tmpE}%
  \fi
  \ifnum\listlen\@findop[2]=1\relax
    \itemtomacro\@findop[2]\tmpB
  \else
    \itemtomacro\@findop[2,2]\tmpD
    \setsepchar{,}%
    \readlist\tmpC{\tmpD}%
    \def\tmpB{\tmpC}%
  \fi
  \if+\@findopsep[1]\relax
    \def\tmp{\vecadd#1}%
  \else\if-\@findopsep[1]\relax
    \def\tmp{\vecsub#1}%
  \else\if.\@findopsep[1]\relax
    \def\tmp{\vecdot#1}%
  \else\if x\@findopsep[1]\relax
    \def\tmp{\veccross#1}%
  \fi\fi\fi\fi
  \expandafter\expandafter\expandafter\tmp\expandafter\tmpA\tmpB
}
\makeatother

\begin{document}
\readlist\A{1,2,3}
\readlist\B{4,5,6}

\vecadd\C\A\B
\C[]

VP:\vecparse\C{\A+\B}
\C[]

\vecsub\C\A\B
\C[]

VP:\vecparse\C{\A - \B}
\C[]

\vecdot\C\A\B
\C[]

VP:\vecparse\C{\A .\B}
\C[] 

\veccross\C\A\B
\C[]

VP:\vecparse\C{\A x\B}
\C[]

VP:\vecparse\C{\A x(3,5,6)}
\C[]

VP:\vecparse\C{(3,5,6)x\B}
\C[]

VP:\vecparse\C{(1,1,1)x(1,2,3)}
\C[]

\end{document}

在此处输入图片描述

答案3

事实证明Henri Menke 提交允许检索符号坐标的原始坐标:有一个命令\coord可以与calc提供原始输入坐标的库一起使用。然后很容易添加一些解析这些坐标的函数。

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\pgfmathdeclarefunction{xcomp3}{3}{% x component of a 3-vector
\begingroup%
  \pgfmathparse{#1}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{ycomp3}{3}{% y component of a 3-vector
\begingroup%
  \pgfmathparse{#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}  
\pgfmathdeclarefunction{zcomp3}{3}{% z component of a 3-vector
\begingroup%
  \pgfmathparse{#3}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{veclen3}{3}{% 3d vector length
\begingroup%
  \pgfmathparse{sqrt(pow(#1,2)+pow(#2,2)+pow(#3,2))}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\newcommand{\spaux}[6]{(#1)*(#4)+(#2)*(#5)+(#3)*(#6)}   
\pgfmathdeclarefunction{scalarproduct}{2}{% scalar product of two 3-vectors
  \begingroup%
  \pgfmathparse{\spaux#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup} 
\newcommand{\vpauxx}[6]{(#2)*(#6)-(#3)*(#5)}     
\newcommand{\vpauxy}[6]{(#4)*(#3)-(#1)*(#6)}
\newcommand{\vpauxz}[6]{(#1)*(#5)-(#2)*(#4)}
\pgfmathdeclarefunction{vpx}{2}{% x component of vector product
  \begingroup%
  \pgfmathparse{\vpauxx#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{vpy}{2}{% y component of vector product
  \begingroup%
  \pgfmathparse{\vpauxy#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{vpz}{2}{% z component of vector product
  \begingroup%
  \pgfmathparse{\vpauxz#1#2}%
  \pgfmathsmuggle\pgfmathresult\endgroup}
\newcommand{\VP}[2]{% macro for vector product (not a function)
\pgfmathsetmacro\myx{vpx({#1},{#2})}%
\pgfmathsetmacro\myz{vpy({#1},{#2})}%
\pgfmathsetmacro\myy{vpz({#1},{#2})}%
(\myx,\myy,\myz)}
\begin{document}
\begin{tikzpicture}
 \path (1,2,3) coordinate (a) (5,6,7) coordinate (b);
 \path  let \p1=(a),\p2=(b)  in (0,-1) 
  node{$(a)=\coord1,(b)=\coord2,
  \pgfmathsetmacro\myx{xcomp3\coord1}a_x=\myx,
  \pgfmathsetmacro\myz{zcomp3\coord2}b_z=\myz,
  \pgfmathsetmacro\myd{scalarproduct({\coord1},{\coord2})}
  \vec a\cdot\vec b=\myd,%
  \pgfmathsetmacro\myvpx{vpx({\coord1},{\coord2})}
  \pgfmathsetmacro\myvpz{vpy({\coord1},{\coord2})}
  \pgfmathsetmacro\myvpy{vpz({\coord1},{\coord2})}
  \vec a\times\vec b=(\myvpx,\myvpy,\myvpz)=\VP{\coord1}{\coord2}
  $};
\end{tikzpicture} 
\end{document}

在此处输入图片描述

只要你在一个框架中工作,你就可以用一种简单的方式解析所有这些内容。然而,原始坐标不记得它们是在哪个框架中定义的。(请注意,还有命令\rawx\rawy\rawz,其用途在下文中描述这里这里。 他们是不是\coord与以 3d 形式声明它们的三个条目相混淆。)

笔记:可以找到一些进一步的发展这里。它们允许您构建线性组合并计算 3d 中符号坐标的矢量积。

相关内容