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, 2014 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.) Dec 30, 2014 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, 2014 at 2:34

1 Answer 1


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)? Dec 30, 2014 at 2:44
  • @emacsomancer Yes. That's what the calc library lets you do.
    – cfr
    Dec 30, 2014 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]. Dec 30, 2014 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, 2014 at 7:24
  • @Kpym: Did you mean that \coordinate[my dot=a]; can replace \node (a)[my dot=a] {};?
    – vtfs271232
    Mar 31, 2021 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.