Is there a simpler way of drawing relation maps?

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

\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,backgrounds,decorations.text,patterns}
\usetikzlibrary{plotmarks}

\begin{document}
\begin{tikzpicture}
\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);
\node at (2,16pt) {\pgfuseplotmark{*}};
\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);
\node at (2,-15pt) {\pgfuseplotmark{*}};
\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);
\node at (1.7,2pt) {\pgfuseplotmark{*}};
\node[above] at (1.7,2pt) {d};

\end{scope}
\end{tikzpicture}
\end{document}


Produces:

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
• 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:

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{shapes,positioning,fit,calc}

\begin{document}
\begin{tikzpicture}
[
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] {};
\end{tikzpicture}
\end{document}


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
• @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