# how one can write a nice vector parser, something that does \pgfvecparse{\A=\B-\C; \D=\E x \F;}

I am often use coordinates of points to draw figure in geometry. I know that, we can add, minus coordinates of points, example

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


If I have two points A(1,2,3) and B(4,5,6), how can I define vector AB as (\B)-(\A)?

• Among the existing proposals, to my knowledge this one might be the most promising one. The open problem, though, is that the transformation is to "recorded". Some advanced transformation recording can be found here. But it seems that you are looking for something else. – user121799 Apr 1 '19 at 2:22
• Asymptote is a good choice – Black Mild Apr 1 '19 at 5:51
• The bad news for you is that TikZ do not keep track of the 3d points. The code (1,2,3) is just fancy interface for a 2d point (that is a projection of this 3d point). – Kpym Apr 1 '19 at 9:30
• @user121799, This (bounty) was a big surprise for me. – ferahfeza Aug 8 '19 at 22:02

If you use the coordinates only for drawing, simply define each components of points as variable and then define coordinate points using them. For example:

\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}


SUPPLEMENT

With the permission of the answerer, I (Steven B Segletes) show here how the listofitems package can be used to streamline the syntax and maybe provide more readability. With it, I can create the arrays by reading a list, with the syntax \readlist\A{2,4,3}. Then, the expression \A[] will spit back the array 2,4,3, which is sufficient for use in the present MWE. However, the individual components are also accessible as \A[1], \A[2], and \A[3], which can be used for various calculations, as required.

\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)
\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}

• Would you mind if I added a supplement to your answer? – Steven B. Segletes Apr 1 '19 at 1:27
• @StevenB.Segletes, sure. I'd appreciate it. – ferahfeza Apr 1 '19 at 6:59
• @ferahfeza margin = 3.14159mm wicked! – L. F. Apr 1 '19 at 9:58
• Since language gap can easily occur on an international site as this, I would note for your benefit that "wicked" is a euphemism common to the Northeastern region of the United States, to mean "especially good." Thus, @L.F. was paying you a compliment, not the opposite. – Steven B. Segletes Apr 1 '19 at 10:43
• Oh don't worry or fret. I recall being similarly confused the first time I visited Maine, U.S. ...and I live less than 500 miles away from there and speak nominally the same language.. – Steven B. Segletes Apr 1 '19 at 10:52

Just for fun, I wrote routines for 3D vector addition, subtraction, cross product and dot product (scalar treated as a 1D vector). I was trying to actually parse expressions of the form \A+\B but eventually gave up.

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

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

\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

\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

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

\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
\makeatother

\begin{document}

\C[]

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

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

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


SUPPLEMENT

I hope John doesn't mind me (Steven B Segletes) adding his sought-after parser to the code. This allows input of the form \vecparse\C{\A+\B}, \vecparse\C{\A - \B}, \vecparse\C{\A .\B}, and \vecparse\C{\A x\B} (extra spaces of no consequence).

Support added not only for \vecparse\C{\A x\B}, but also \vecparse\C{\A x(3,5,6)}, \vecparse\C{(3,5,6)x\B} and \vecparse\C{(1,1,1)x(1,2,3)}.

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

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

\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{,}%

\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{,}%

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

\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{,}%

\def\vecparse#1#2{%
\setsepchar{+||-||x||./(||)}%
\ifnum\listlen\@findop[1]=1\relax
\itemtomacro\@findop[1]\tmpA
\else
\itemtomacro\@findop[1,2]\tmpF
\setsepchar{,}%
\def\tmpA{\tmpE}%
\fi
\ifnum\listlen\@findop[2]=1\relax
\itemtomacro\@findop[2]\tmpB
\else
\itemtomacro\@findop[2,2]\tmpD
\setsepchar{,}%
\def\tmpB{\tmpC}%
\fi
\if+\@findopsep[1]\relax
\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}

\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}


• That is really nice. – Steven B. Segletes Apr 1 '19 at 19:36
• I hope you don't mind my edit. – Steven B. Segletes Apr 1 '19 at 20:21
• I was thinking more of expressions like \A+(4,5,6) which are a lot easier when \A expands to 1,2,3 directly. – John Kormylo Apr 2 '19 at 13:34
• @marmot I think it would be possible, but would require quite a bit more effort. Any time the input is allowed to be in a free format, requiring sub-evaluations of the components that can than comprise larger components...well a more careful approach is required. – Steven B. Segletes Apr 2 '19 at 15:54
• @marmot It would likely require an approach like tex.stackexchange.com/questions/332012/…, where an order of operations hierarchy is established, and the input parsed along those lines. But rather than just typesetting the result, vector mechanics needs to be performed. – Steven B. Segletes Apr 2 '19 at 16:12

It turns out that a commit by Henri Menke allows one to retrieve the raw coordinates of a symbolic coordinate: there is a command \coord that can be used with the calc library which provides the raw input coordinates. Then it is easy to add some functions that parse these.

\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}


As long as you work in one frame, this allows you to parse all these things in a simple way. The raw coordinates do, however, not remember in which frame they are defined. (Note that there are also the commands \rawx, \rawy and \rawz, whose purpose is described here and here. They are not to be confused with the three entries of \coord in case one has declared them in 3d.)

NOTE: Some further developments of this can be found here. They allow you to build linear combinations and compute vector products of symbolic coordinates in 3d.

• Can this code write an equation of a plane knowing that a point and a normal vector? – minhthien_2016 Aug 20 '19 at 6:54
• @minhthien_2016 This is an analytic computation for which you do not need this code. What precisely do you mean by "equation of a plane"? If you know the normal n and the point a, the equation will be \vec n\cdot (\vec a-\vec r)=0. – user194703 Aug 20 '19 at 7:03
• Thank you very much. I will try to use this your tool. – minhthien_2016 Aug 20 '19 at 7:10
• Can you add an aswer by using this tool at here tex.stackexchange.com/questions/471091/… ? – minhthien_2016 Aug 20 '19 at 14:35
• @minhthien_2016 It would be way cleaner if you write a new question. The answer to tex.stackexchange.com/questions/471091/… was written before the calc library got updated and way before the update of calc made it to CTAN. The routines there seem to work, but can be made more elegant with the parser here. – user194703 Aug 20 '19 at 14:40