1

I am going to need a lot of vector triangles and would like to do them with TikZ. My TikZ experience is close to not existing. Therefore I would like to ask you, if there is a possibility to draw calculated vector triangles (sums) with TikZ.

What I need:

  • three different coloured vectors pointing together in an triangle
  • possibility to define each triangle by "angle-length-angle"
  • maybe the possibility to hide one or two of these arrows.
  • a centred label aligned to the middle of each vector (for mathematical expressions)
  • the anchor point (0,0) should be the conjunction of c and w
  • the vector sum should be w + u or u + w

I want to get speed triangles (for volume flow in a machine). In the end I will position them on included images. Therefore I need the triangles, single vectors, arc vectors (direction of rotation) and vectors into the paper plane (cross in circle [into the paper] and point in circle [out of the paper]) which shall all look similar and recognizable.

Are such calculations possible within TIKZ? Should I take an other package? How can I get plain and technical speed triangle drawings which match the real volume flow?


A sample:

enter image description here

\alpha, \beta and |u| should be chosen by the user. The rest is calculated. Angle definitions between chosen vectors would also be great. E. g.: show angle between positive u and w as \beta

  • Can you scribble in paint what the end result should be ? – percusse Jul 17 '13 at 14:06
  • That's certainly possible. Could you post a sample/sketch of what you have in mind? And any coding attempt you may have? – Count Zero Jul 17 '13 at 14:08
  • Isn’t there at least one variable missing? Another angle or another length? How are the vectors in the paper plane related to the triangles? (If at all, drawing is the easiest part here.) Could you also add your idea on the input syntax or an example of given values/variables? – Qrrbrbirlbel Jul 17 '13 at 14:44
  • 1
    In my post, you have all the tools you need to create those drawings. – dustin Jul 17 '13 at 16:27
  • 1
    I made the vectors boldface for you and had the math parser find and print the angles of alpha and beta so you know everything is done to specification. You should be able to re-create the next two diagrams by analyzing the code. – dustin Jul 17 '13 at 19:36
6

Please see revision 4 for a previous take on Op’s conditions and given variables.

The paper plane vectors are relative easy to produce. As you want to label them, I’d use a node with a custom path picture. Common properties are saved in the paper plane vector. The optional argument to paper plane vector in and paper plane vector out can be used to change the label.

As both triangles are rather hard to generalize, I created two distinctive but similar styles

  • vector triangle u+w and
  • vector triangle w+u.

The both accept four arguments, delimited by :. (I agree, both names and arguments could be chosen better.) Those arguments are:

  1. Angle α,
  2. angle β,
  3. length of vector w,
  4. an index for the edge nodes (it will be forwarded to the edge styles).

Further styles exist for

  • the angle marking @vector triangle angle (parameter 4 and 5 are auxiliary ones for when both angles lie at the same point) and three additional styles
    • for the dashed line,
    • for the arc line and
    • for the arc node;
  • every vector and every vector node, as well as
  • a style for every vector and every vector node (for u, w and c).

The style dashed line will be changed for when it will be under the u vector anyway or when it will be the same as the dashed line from the other angle.

In the u+w style the parallel marking will be appended to dashed line and will also be used for the u vector. The decorations.markings library is used for this.

The last few styles (see the comments in the code) are actually not mandatory as they are accessed with /.try handler. Without them, you will see a very raw version of the drawing.

Code

\documentclass[tikz,convert=false]{standalone}
\colorlet{RED}{red!75!black}
\colorlet{BLACK}{black}
\colorlet{BLUE}{blue!75!black}
\usetikzlibrary{decorations.markings}
\makeatletter
\tikzset{edge node/.code={% stolen from the CVS version
    \expandafter\def\expandafter\tikz@tonodes\expandafter{\tikz@tonodes #1}}}
\makeatother
%% The paper plane vector things
\tikzset{
  paper plane vector/.style={
    shape=circle,
    inner sep=+0pt,
    minimum size=+1em,
    label={#1}
  },
  paper plane vector out/.style={
    paper plane vector={[RED]above left:{$#1$}},
    draw=RED,
    path picture={
      \fill[RED] (path picture bounding box.center) circle [radius=+1.41\pgflinewidth];
    }
  },
  paper plane vector in/.style={
    paper plane vector={[BLACK]above left:{$#1$}},
    draw=BLACK,
    path picture={
      \draw[BLACK] (path picture bounding box.south west) -- (path picture bounding box.north east)
                   (path picture bounding box.south east) -- (path picture bounding box.north west);
    }
  },
  paper plane vector in/.default=u,
  paper plane vector out/.default=w}

%% The parallel marking
\tikzset{
  parallel marking/.style={
    postaction={
      decoration={
        name=markings,
        mark=at position .33 with {\draw[solid,thin,-] (+-6\pgflinewidth,+-4\pgflinewidth) -- ++ (+8\pgflinewidth,+8\pgflinewidth)
                                                       (+-2\pgflinewidth,+-4\pgflinewidth) -- ++ (+8\pgflinewidth,+8\pgflinewidth); }
      },
      decorate}}}

%% The triangles, consisting only of an 'insert path'
\tikzset{
  vector triangle u+w/.style args={#1:#2:#3:#4}{% #1 = alpha,
                                                % #2 = beta,
                                                % #3 = length of w,
                                                % #4 = an argument that gets forwarded to the
                                                %      edges, here an index
    insert path={
       coordinate (vt@o)
       +({90+#2}:{#3}) coordinate (vt@c)
       {[dashed line/.append style=parallel marking, @vector triangle angle={vt@o}{#2}{\beta}{0}{0}]}
       {[dashed line/.style={draw=none},@vector triangle angle={vt@o}{#1}{\alpha}{.1}{#2}]}
       (intersection of vt@o--[shift={(90+#1:20)}] vt@o and vt@c--[shift={(down:20)}] vt@c) edge[u vector/.try={#4},parallel marking] (vt@c)
                                                                                            edge[c vector/.try={#4}] (vt@o)
                                                                                     (vt@c) edge[w vector/.try={#4}] (vt@o)
    }
  },
  vector triangle w+u/.style args={#1:#2:#3:#4}{% #1 = alpha,
                                                % #2 = beta,
                                                % #3 = length of w,
                                                % #4 = an argument that gets forwarded to the
                                                %      edges, here an index
    insert path={
       coordinate (vt@o)
       + ({90+#2-180}:{#3}) coordinate (vt@c)
       (intersection of vt@o--[shift={({#1-90}:20)}] vt@o and vt@c--[shift={(up:20)}] vt@c) coordinate (vt@aux)
       [@vector triangle angle={vt@aux}{#1}{\alpha}{0}{0}]
       {[dashed line/.style={draw=none},@vector triangle angle={vt@c}{#2}{\beta}{0}{0}]}
       (vt@o) edge[w vector/.try={#4}] (vt@c)
              edge[c vector/.try={#4}] (vt@aux)
       (vt@c) edge[u vector/.try={#4}] (vt@aux)
    }
  },
  %% The angle drawing, the arguments #4 and #5 are only for angles that overlap (see the u+w style why), usually the ary '0'
  @vector triangle angle/.style n args={5}{
    insert path={
      (#1) edge[dashed line/.try] ++ (up:1)
      ++(up:.75+#4) edge[arc line/.try, to path={arc [radius=.75+#4, start angle=90, delta angle={#2}]}] ()
      node [rotate={#5+(#2-#5)/2}, arc node/.try] at ([shift=({90+#5+(#2-#5)/2}:.5)] #1) {$#3$}}}}

%% A few presets for the vectors and nodes.
%% If these are not given, the drawing will still work (the '.try' handler takes care of that)
%% but you will have a raw version (try it!)
\tikzset{
  every vector/.style 2 args={shorten >=\pgflinewidth,->,edge node={node[#1 node/.try] {$\vec{#1}_{#2}$}}},
    w vector/.style={every vector={w}{#1},RED},
    u vector/.style={every vector={u}{#1},BLACK},
    c vector/.style={every vector={c}{#1},BLUE},
  every vector node/.style={below,sloped,text={#1}},
    w node/.style={every vector node=RED},
    u node/.style={every vector node=BLACK},
    c node/.style={every vector node=BLUE,above},
  dashed line/.style={thin, densely dotted, line cap=butt},
  arc line/.style={thin, solid, ->, line cap=butt, shorten >=.5\pgflinewidth, shorten <=.5\pgflinewidth},
  arc node/.style={font=\scriptsize},
}
\begin{document}
\begin{tikzpicture}[>=latex,line cap=round]
  \node[paper plane vector in] {};
  \node[paper plane vector out] at (-1,0) {};

  \path (-1,-2) [vector triangle w+u=105:45:4.5:1];

  \path (7,-3)  [vector triangle u+w=105:45:4.5:2];
\end{tikzpicture}
\end{document}

Output

enter image description here


enter image description here

  • I know I shall just upvote (as I did on all posts) but thanks for this great effort and those high class results. – LaRiFaRi Jul 17 '13 at 18:46
  • If I may ask for more, it would be nice to get the angle labels rotated by half the angle as it is done in technical drawings. (And as I don't dare to edit your post, maybe also a \vec{...} to the three vector labels, as I will print the letter bold (or others with a vector arrow)) – LaRiFaRi Jul 17 '13 at 18:59
  • 1
    @LaRiFaRi I’ve updated my answer to include the rotation and the \vec. Due the use of styles I only needed to change things in two placed. Given that u is always vertical (and hasn’t a given length) it is even easier (and fully defined of course). – Qrrbrbirlbel Jul 17 '13 at 20:43
  • Beautiful. Actually u has a length (still confusing from my made errors). So the path should be defined by % #1 = alpha, % #2 = beta, % #3 = orientation of u,% #4 = length of u,... where #3 = +90° by default. I think that would give mathematical correctness to that problem. – LaRiFaRi Jul 17 '13 at 21:16
  • I don't succeed with this change: paper plane vector out/.style args={#1:#2:#3}{paper plane vector={[#3]above left:{$\vec{#1}_{#2}$}}, draw=#3, path picture={\fill[#3] (path picture bounding box.center) circle [radius=+1.41\pgflinewidth];}} which shall be used as \node[paper plane vector out] at (-1,0) {c:\text{m}:BLUE};. Why? – LaRiFaRi Jul 18 '13 at 7:19
6

I drew your left triangle and you can adjust the techniques to construct the second triangle or any others.

At the bottom, I explained what the code was doing. If you need any further explanations so you can re-create other examples with it, just ask.

\documentclass[convert = false, border = 2cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc, intersections, arrows}

\begin{document}

\begin{tikzpicture}
  \coordinate (O) at (0, 0);

  \draw[-latex] (O) -- +(2, 0) coordinate (P1) node[pos = .5, above]
  {\(c_2\)};

  \path[name path = line1] (P1) -- +(0, -5);
  \path[name path = line2] (O) -- (-45:4cm);
  \path[name intersections = {of = line1 and line2, by = P2}];

  \draw[-latex, red] (O) -- (P2) node[pos = .5, below] {\(w_1\)};
  \draw[-latex] (P2) -- (P1) node[pos = .5, right] {\(v_1\)};

  \draw[shorten >=.5\pgflinewidth, shorten <=.5\pgflinewidth, -latex, red] 
  let
    \p0 = (P2),
    \p1 = (P1),
    \p2 = (O),
    \n1 = {atan2(\x1 - \x0, \y1 - \y0)},
    \n2 = {atan2(\x2 - \x0, \y2 - \y0)},
    \n3 = {1cm},
    \n4 = {(\n1 + \n2) / 2}
  in (P2) -- +(\n1:\n3) arc[radius = \n3, start angle = \n1, end angle = \n2]
  node at ([shift = (P2)] \n4:.5cm) {\(\alpha_1\)};
\end{tikzpicture}

\end{document}

I started by labelling the origin as (O). From the (O), we can use -- +() to specify a distance from the origin. In this example, I said over 2 up 0 and I then labelled the end of the vector (P1).

Next, I used the path commands to draw a line straight down from (P1) and a line with polar coordinates -45 degrees and radius 4cm. As you see, I named both the lines for use with the intersections library.

With the intersections library, I found where the two paths meet and labelled it (P2). Now, we have a coordinate we can direct from and to with the other vectors.

Lastly, I used the \draw let .. in command to find the angle and draw the arc between the two vectors.

As Qrrbrbirlbel suggested, we don't need on background layer if we add \draw[shorten >=.5\pgflinewidth, shorten <=.5\pgflinewidth, -latex, red]

enter image description here

To create you first triangle in your edited post, all I needed to do was change:

  \coordinate (O) at (0, 0);

  \begin{pgfinterruptboundingbox}
    \path[name path = line1] (O) -- (15:7cm);

    \draw[-latex, red] (O) -- (-45:4.5cm) coordinate (P1) node[pos = .5,
    below left, rotate = -45]
    {\(\mathbf{w}\)};

    \path[name path = line2] (P1) -- +(0, 7cm);
    \path[name intersections = {of = line1 and line2, by = P2}];
  \end{pgfinterruptboundingbox}   

  \draw[-latex, blue] (O) -- (P2) node[pos = .5, above, rotate = 15] {\(\mathbf{c}\)};
  \draw[-latex] (P1) -- (P2) node[pos = .5, right] {\(\mathbf{u}\)};
  \draw[dashed] (P2) -- +(0, 1.5cm) coordinate (P3);

  \draw[-latex] let
    \p0 = (P2),
    \p1 = (P3),
    \p2 = (O),
    \n1 = {atan2(\x1 - \x0, \y1 - \y0) - 360},
    \n2 = {atan2(\x2 - \x0, \y2 - \y0)},
    \n3 = {.75cm},
    \n4 = {(\n1 + \n2) / 2}
  in (P2) +(\n1:\n3) arc[radius = \n3, start angle = \n1, end angle = \n2]
  node at ([shift = (P2)] \n4:.5cm) {\(\alpha\)};

  \draw[-latex] let
    \p0 = (P1),
    \p1 = (P2),
    \p2 = (O),
    \n1 = {atan2((\x1 - \x0) / (\y1 - \y0), 1)}, %see link for explanation here
    \n2 = {atan2(\x2 - \x0, \y2 - \y0)},
    \n3 = {.75cm},
    \n4 = {(\n1 + \n2) / 2}
  in (P1) +(\n1:\n3) arc[radius = \n3, start angle = \n1, end angle = \n2]
  node at ([shift = (P1)] \n4:.5cm) {\(\beta\)};

There was an error with the second \draw let .. in command so I asked a question about it. You can read the details of it here TikZ: When I use the draw let ... in command to draw a trivial arc, I get dimension too large and why \n1 is different in this case.

enter image description here

With TikZ, we can use the math parser to calculate the angles. Therefore, we can verify that everything is exact to the drawing specifications.

\documentclass[convert = false, border = 1cm]{standalone}
\usepackage{tikz, fp}
\usetikzlibrary{calc, intersections, arrows, fixedpointarithmetic}

\begin{document}
\begin{tikzpicture}[fixed point arithmetic]
\coordinate (O) at (0, 0);

\begin{pgfinterruptboundingbox}
  \path[name path = line1] (O) -- (15:7cm);

  \draw[-latex, red] (O) -- (-45:4.5cm) coordinate (P1) node[pos =   .5,
  below left, rotate = -45]
  {\(\mathbf{w}\)};

  \path[name path = line2] (P1) -- +(0, 7cm);
  \path[name intersections = {of = line1 and line2, by = P2}];
\end{pgfinterruptboundingbox}

\draw[-latex, blue] (O) -- (P2) node[pos = .5, above, rotate = 15]
{\(\mathbf{c}\)};
\draw[-latex] (P1) -- (P2) node[pos = .5, right] {\(\mathbf{u}\)};
\draw[dashed] (P2) -- +(0, 1.5cm) coordinate (P3);

\draw[-latex] let
\p0 = (P2),
\p1 = (P3),
\p2 = (O),
\n1 = {atan2(\x1 - \x0, \y1 - \y0) - 360},
\n2 = {atan2(\x2 - \x0, \y2 - \y0)},
\n3 = {.75cm},
\n4 = {(\n1 + \n2) / 2}
in (P2) +(\n1:\n3) arc[radius = \n3, start angle = \n1, end angle = \n2]
node at ([shift = (P2)] \n4:.5cm) {\(\alpha\)} node[above] at
([shift = (P2)] \n4:\n3) {\pgfmathparse{\n2 - \n1}%                                 
  $\pgfmathprintnumber{\pgfmathresult}^{\circ}$
};

\draw[-latex] let
\p0 = (P1),
\p1 = (P2),
\p2 = (O),
\n1 = {atan2((\x1 - \x0) / (\y1 - \y0), 1)}, %see link for explanation here         
\n2 = {atan2(\x2 - \x0, \y2 - \y0)},
\n3 = {.75cm},
\n4 = {(\n1 + \n2) / 2}
in (P1) +(\n1:\n3) arc[radius = \n3, start angle = \n1, end angle = \n2]
node at ([shift = (P1)] \n4:.5cm) {\(\beta\)} node[above] at
([shift = (P1)] \n4:\n3) {\pgfmathparse{\n2 - \n1}%                                 
  $\pgfmathprintnumber{\pgfmathresult}^{\circ}$
};
\end{tikzpicture}
\end{document}

enter image description here

Per LaRiFaRi comment, the code works as requested if you change

\draw[-latex, red] (O) -- (0:4.5cm) coordinate (P1) node[pos =   .5,
    below left, rotate = 0]
    {\(\mathbf{w}\)};

enter image description here

  • 2
    You don’t need the on background layer scope if you remove the -- from the path and add the options shorten >=.5\pgflinewidth, shorten <=.5\pgflinewidth (given that angle arrow and the vector arrows have the same line width) and the angle arrow would only touch the red vector line. – Qrrbrbirlbel Jul 17 '13 at 15:50
  • Incredible how fast you all are. Very impressive. I edited my example above. Now it should be clear. The labels should be rotated if possible. Your examples already look beautiful. I will check the technique tomorrow as I have to go. Thanks. – LaRiFaRi Jul 17 '13 at 16:14
  • I'm having three problems with your solution. When I set \beta to 90° the lower half of the arrow is cut away. When I try to set the labels as \vec{c}_\text{rad} I am getting an Undefined control sequence. When I rotate u by 90°, it doesn't stay next to the vector. – LaRiFaRi Jul 18 '13 at 11:09
  • 1
    @LaRiFaRi What do you mean when you set beta? I don't have it setup for beta to be coded in. To rotate u, chage right to below and type in rotate = 90 – dustin Jul 18 '13 at 11:21
  • 1
    @LaRiFaRi it just worked for me. I changed that line to what you said in the comment. See my updated post. – dustin Jul 18 '13 at 12:44
3

I think all of that should be possible with tikz (with \usetikzlibrary{calc,intersections} at least).

Here a simple example with a macro that takes 2 arguments (relative coordinates - polar or cartesian - whatever floats your boat) and an optional 3rd argument which should be the absolute coordinate of the beginning of the triangle (default is (0,0)).

\documentclass{article}
\usepackage{tikz}
%\usetikzlibrary{calc}%,intersections}
\begin{document}

\newcommand{\TR}[3][0,0]{
\coordinate(E0) at (#1);
\draw[-latex](#1)--+(#2)coordinate(E1)node[pos=0.5,sloped](M0){};\coordinate(M0)at(M0);
\draw[-latex](E1)--+(#3)coordinate(E2)node[pos=0.5,sloped](M1){};\coordinate(M1)at(M1);
\draw[-latex](E2)--(E0)node[pos=0.5,sloped](M2){};\coordinate(M2)at(M2);
}

\begin{tikzpicture}
\TR{10:5}{100:3}
%\TR[10:5]{20:3}{110:8}
\draw(M2)circle(5pt);
\filldraw[green](E0)circle(5pt);

\TR[M0]{270:1}{30:2}
\TR[M1]{270:1}{30:2}%Using mid of old triangle for starting point of new triangle
\TR[M1]{270:1}{30:2}
\TR[M1]{270:1}{30:2}
%\TR[M2]{20:3}{110:8}
\end{tikzpicture}
\end{document}

enter image description here

Thats just basic tikz- stuff - more advanced calculations are done with calc, e.g.:

($0.5*(A)+0.5*(B)$)

calculates the center point of the (cartesian) coordinates A and B.

Also projections are possible

($(A)!(C)!(B)$)

like this.

More on calc here: List of available TikZ libraries with a short introduction

Hiding the arrows could be done by using some styles in the macros and changing these styles before calling the macro.

But beware - to complex macros make things harder to read and also difficult to maintain if not written properly (even then it can get tedious).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.