11

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. –  Apr 01 '19 at 02:22
  • Asymptote is a good choice – Black Mild Apr 01 '19 at 05: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 01 '19 at 09:30
  • @user121799, This (bounty) was a big surprise for me. –  Aug 08 '19 at 22:02

3 Answers3

8

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}

enter image description here


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)
\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}
  • 1
    Would you mind if I added a supplement to your answer? – Steven B. Segletes Apr 01 '19 at 01:27
  • @StevenB.Segletes, sure. I'd appreciate it. –  Apr 01 '19 at 06:59
  • 1
    @ferahfeza margin = 3.14159mm wicked! – L. F. Apr 01 '19 at 09:58
  • @L.F., many TiKzperts use it here. Why is mine wicked? –  Apr 01 '19 at 10:24
  • @ferahfeza Really! So TikZperts are wicked in general! ;-) – L. F. Apr 01 '19 at 10:25
  • @StevenB.Segletes, I hadn't heard of the listofitems package. Thank you very much. –  Apr 01 '19 at 10:28
  • 1
    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 01 '19 at 10:43
  • I'm happy to reveal listofitems for your benefit. It is a very useful and versatile package. – Steven B. Segletes Apr 01 '19 at 10:45
  • @ferahfeza So sorry about that! I was completely unaware that my joke would cause that much misapprehension! – L. F. Apr 01 '19 at 10:46
  • @StevenB.Segletes, I'm so embarrassed now. I didn't know this detail. I apologize to L.F. and thank you both. –  Apr 01 '19 at 10:47
  • @L.F., Steven B .Segletes explained it very well. No problem. I'm happy to learn something new. Thank you. –  Apr 01 '19 at 10:49
  • 1
    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 01 '19 at 10:52
5

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


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

enter image description here

John Kormylo
  • 79,712
  • 3
  • 50
  • 120
  • That is really nice. – Steven B. Segletes Apr 01 '19 at 19:36
  • I hope you don't mind my edit. – Steven B. Segletes Apr 01 '19 at 20:21
  • No problem. OTOH I am having second thoughts about using lists for vectors instead of \edef\A{1,2,3} and only using lists to parse them. – John Kormylo Apr 02 '19 at 13:17
  • listofitems has a provided macro, \itemtomacro that might help in that regard, for extracting parts of or the whole of a list. I probably should have used it to assign \tmpA and \tmpB. ... I just did. – Steven B. Segletes Apr 02 '19 at 13:27
  • 1
    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 02 '19 at 13:34
  • John, First, I noticed you have an error in your \veccross definition for \@z. But I also took care of the parsing issue allowing for raw vector input. – Steven B. Segletes Apr 02 '19 at 14:44
  • RE \veccross; oops. Must have been a typo ;-) – John Kormylo Apr 02 '19 at 14:54
  • @StevenB.Segletes Do you think it is possible to do something like \vecparse{\C=\A - \B} or \vecparse{\D=\C x (\A - \B)} or even \vecparse{D=C x (A - B)}? (The TikZ library math allows one to do some of these things for 2D vectors.) –  Apr 02 '19 at 15:48
  • 1
    @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 02 '19 at 15:54
  • 1
    @marmot It would likely require an approach like https://tex.stackexchange.com/questions/332012/translate-in-line-equations-to-tex-code-any-package/332061#332061, 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 02 '19 at 16:12
  • @StevenB.Segletes I had already upvoted that one. ;-) Yes, these are all very helpful tools. (My main problem is that there is a second issue: establishing an "absolute reference frame". The way TikZ does that in 2D is just to use absolute page coordinates and that works fine. All one needs to do is to keep track of the 2D transformations, but this is an Abelian group and hence not too difficult. In 3D the hell breaks loose because the transformations form a non-Abelian group. This is why it will be tough to extend the 2D features to 3D....) –  Apr 02 '19 at 16:35
  • It appears there is a typographical error in this definition of the dot product \vecdot: #2[1]*#3[1] + #2[2]*#3[2] + #3[3]*#3[3]}

    The final component of the dot product uses component 3 of vector B twice, rather than using components 3 from both vector A and vector B. So the code should read:

    #2[1]*#3[1] + #2[2]*#3[2] + #2[3]*#3[3]}

    – Charles B. Cameron Sep 04 '23 at 08:35
  • @CharlesB.Cameron - Thanks, fixed. – John Kormylo Sep 04 '23 at 12:52
2

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}

enter image description here

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 06:54
  • 1
    @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. –  Aug 20 '19 at 07:03
  • Thank you very much. I will try to use this your tool. – minhthien_2016 Aug 20 '19 at 07:10
  • Can you add an aswer by using this tool at here https://tex.stackexchange.com/questions/471091/is-there-a-command-to-find-coordinates-of-projection-of-a-point-on-a-plane ? – minhthien_2016 Aug 20 '19 at 14:35
  • @minhthien_2016 It would be way cleaner if you write a new question. The answer to https://tex.stackexchange.com/questions/471091/is-there-a-command-to-find-coordinates-of-projection-of-a-point-on-a-plane 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. –  Aug 20 '19 at 14:40
  • Please see my new question at https://tex.stackexchange.com/questions/505037/is-there-a-simpler-answer-to-find-projection-of-a-point-on-a-plane – minhthien_2016 Aug 21 '19 at 01:07