For an example relation R: A -> B, I have the following TikZ code:


  \begin{scope}[mark=*,mark size=1pt]
% sets A & B
  \draw (0,0) node[ellipse, minimum height=50pt,minimum width=30pt,draw,label=above:A]{};
  \draw (2,0) node[ellipse, minimum height=50pt,minimum width=30pt,draw,label=above:B]{};
% draw line and label origin a to c
  \draw[->] plot coordinates {(0,10pt)} (0,10pt) node[above]{a} -- (1.9,16pt);
% add end point
  \node at (2,16pt) {\pgfuseplotmark{*}};
% add end label
  \node[above] at (2,16pt) {c};
% draw line and label origin a to e
  \draw[->] plot coordinates {(0,10pt)} (0,10pt) node[above]{a} -- (1.9,-15pt);
% add end point
  \node at (2,-15pt) {\pgfuseplotmark{*}};
% add end label
  \node[above] at (2,-15pt) {e};
% draw line and label origin b to d
  \draw[->] plot coordinates {(0,-10pt)} (0,-10pt) node[above]{b} -- (1.6,2pt);
 % add end point
  \node at (1.7,2pt) {\pgfuseplotmark{*}};
% add end label
  \node[above] at (1.7,2pt) {d};



enter image description here

Is there a simpler way of accomplishing this in TikZ? It seems like a lot of work.

  • Pencil and paper? – cfr Dec 30 '14 at 2:00
  • I'm preparing lecture slides, which I wanted to be semi-self-contained. (Of course lots of things can be easily drawn on black|whiteboards.) – emacsomancer Dec 30 '14 at 2:31
  • 1
    It wasn't intended as a serious suggestion ;). My answer is serious. My comment is not. [Well, this comment is more serious but it discusses my other, non-serious comment. Moreover, while more serious, even this one ought not be taken too seriously.] – cfr Dec 30 '14 at 2:34

No doubt requires adjustment since I'm not aware of the applicable criteria:


      group/.style={ellipse, draw, minimum height=50pt, minimum width=30pt, label=above:#1},
      my dot/.style={circle, fill, minimum width=2.5pt, label=above:#1, inner sep=0pt}
    \node (a) [my dot=a] {};
    \node (b) [below=of a, my dot=b] {};
    \node (c) [right=50pt of a, my dot=c] {};
    \node (e) [below=of c, my dot=e] {};
    \node (d) [xshift=-2.5pt, my dot=d] at ($(c)!1/2!(e)$) {};
    \foreach \i/\j in {a/c,a/e,b/d}
      \draw [->, shorten >=2pt] (\i) -- (\j);
    \node [fit=(a) (b), group=A] {};
    \node [fit=(d) (c) (e), group=B] {};


This uses styles to minimise repetition of code. In particular, it uses styles which use an argument (#1) for the label. It also uses the fit library for the ellipses and the positioning and calc libraries to help in specifying locations. This makes it possible to save quite a lot of code. Finally, a loop is used to draw the arrows although this might not really be worth the trouble if you only have 3 arrows to draw - it really comes into its own, though, if you have something more like 30.

  • $(c)!1/2!(e)$ means half-way between position of (c) and (e)? – emacsomancer Dec 30 '14 at 2:44
  • @emacsomancer Yes. That's what the calc library lets you do. – cfr Dec 30 '14 at 2:47
  • Thanks, by the way. This set up makes it (relatively) easy to produce various mappings of this sort [which is what I was looking for]. – emacsomancer Dec 30 '14 at 3:05
  • 1
    @cfr Off topic : you can add in your style my dot the code name=#1 and then use it as \coordinate[my dot=a];. – Kpym Dec 30 '14 at 7:24
  • @Kpym: Did you mean that \coordinate[my dot=a]; can replace \node (a)[my dot=a] {};? – Kim Jong Un Mar 31 at 11:36

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.