How to draw penrose diagrams with TikZ
The following code should get you started. Since I asume you are a tikz beginner, I'll provide some basic explanations after the code:
Code
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
\begin{document}
\begin{tikzpicture}
\node (I) at ( 4,0) {I};
\node (II) at (-4,0) {II};
\node (III) at (0, 2.5) {III};
\node (IV) at (0,-2.5) {IV};
\path % Four corners of left diamond
(II) +(90:4) coordinate[label=90:$i^+$] (IItop)
+(-90:4) coordinate[label=-90:$i^-$] (IIbot)
+(0:4) coordinate (IIright)
+(180:4) coordinate[label=180:$i^0$] (IIleft)
;
\draw (IIleft) --
node[midway, above left] {$\cal{J}^+$}
node[midway, below, sloped] {$\bar{u}=\infty$}
(IItop) --
node[midway, below, sloped] {$\bar{u}=0$}
(IIright) --
node[midway, below, sloped] {$\bar{u}=0$}
(IIbot) --
node[midway, above, sloped] {$\bar{v}=-\infty$}
node[midway, below left] {$\cal{J}^-$}
(IIleft) -- cycle;
\path % Four conners of the right diamond (no labels this time)
(I) +(90:4) coordinate (Itop)
+(-90:4) coordinate (Ibot)
+(180:4) coordinate (Ileft)
+(0:4) coordinate (Iright)
;
% No text this time in the next diagram
\draw (Ileft) -- (Itop) -- (Iright) -- (Ibot) -- (Ileft) -- cycle;
% Squiggly lines
\draw[decorate,decoration=zigzag] (IItop) -- (Itop)
node[midway, above, inner sep=2mm] {$r=0$};
\draw[decorate,decoration=zigzag] (IIbot) -- (Ibot)
node[midway, below, inner sep=2mm] {$r=0$};
\end{tikzpicture}
\end{document}
Result
Explanations
Tikz has a syntax very powerful and versatile. You can specify the coordinates of your drawing in different ways.
- The first and more straighforward one is to use standard cartesian coordinates, such as
(4,0)
. The default unit iscm
. - You can also specify polar coordinates, for example
(90:4)
. The first number is the angle, the second the radius (again in cm by default). - You can give a name to a coordinate, and use its name, as for example
(I)
or(II)
- When building a path, you can specify the coordinates as absolute (all are measured wuth respect the origin which is at
(0,0)
) or relative (all are measured with respect to some given origin). For relative syntax precede the coordenate by+
. For giving the origin, specify a first coordinate without the+
.
With the above, you can read now the first few lines. Each of the initial \node
commands define a named coordinate, with names (I)
, (II)
and so on, at the given absolute cartesian coordinates (4,0)
, (-4,0)
and so on). Also they place some text at those coordinates (the text between braces {I}
, {II}
, etc.)
The next \path
command does a lot of things. It starts by setting the coordinate (II)
as the origin for the remaining relative coordinates. Then, using polar coordinates relative to (II)
, some other named coordinates are defined, at right angles around (II)
and distance 4
units. I named those coordinates (IItop)
, (IIbot)
etc, using another syntax which uses the keyword coordinate
as part of a path. At same time I typeset some labels a those coordinates, using the label
option.
Once the four corners of the diamond are defined that way, they are joined with lines, and some labels are added above and below those lines. This is done in the next \draw
command. The --
between two coordinates specifies that a line should be drawn. Before the final coordinate of each segment I use the node
keyword to place text above and below those lines.
For the right diamond I removed all labels, and left only the drawing commands. Placing the labels should be almost identical to the first diamond and it's left as exercise.
Finally, the squiggly lines are added, connecting the appropiate coordinates at top and bottom of the diamond. I use again a node[midway]
to place some text above (or below) those lines.
Hope this helps to get you started, or at least to motivate you to read the manual and give Tikz a try.
Update
The OP requested in a comment:
to draw a curved path from what you have called
Ibot
to the centre of the squigly line at the top ofIII
labelledr=0
. This could pass roughly 0.75 the way through the line that joinsIIright
andItop
.
This gives me the opportuniy of introducing other useful Tikz capability, which are calculated coordinates. In order to use this feature you need to add calc
to the list of \usetikzlibrary
arguments. In this case:
\usetikzlibrary{decorations.pathmorphing,calc}
Thanks to this library you can use at any place at which a coordinate is required, a mathematical expression (enclosed by $
) involving addition or other operations with coordinates. It also defines a special operation called "interpolation", which has the following syntax: ($(A)!x!(B)$)
, where A
and B
are coordinates (cartesian, polar, named ones...) and x
is a number between 0 and 1. The resulting coordinate is a point located in the line A-B, at a point proportional to x
(0 means A, 1 means B). In fact, x can be negative or greater than 1, allowing extrapolation.
Using this feature, the pont "at the middle of the top squiggley line" would be: ($(IItop)!.5!(Itop)$)
, so the next command would draw a straight line connecting the two required points:
\draw[->] % The -> adds an arrow tip
(Ibot) -- ($(IItop)!.5!(Itop)$);
But the OP requested a curved line, not a straight one. To get a curved line, the easiest way (tikz also has several ways) is to replace --
by the to
operator. This operator without options draws a straight line, the samen than --
, but you can give options to it to bend the line.
For example, you can specify the angle at which the line leaves from Ibot
, and the angle at which it should enter at the final point. This produces a curve. However, those parameters alone does not define a single curve, but a family of curves. You can fine-tune the curve obtained with the parameter looseness
, which is 1 by default. Increasing this parameter makes the curve "more curve", and reducing it makes the curve more close to the original straight line.
By trial and error I've found these values:
\draw[->]
(Ibot) to[out=70, in=-15, looseness=1.5] ($(IItop)!.5!(Itop)$);
And the result is:
One possibility (as JLDiaz mentions in his comment) is to use coordinates to specify points, and then draw the lines joining the appropriate coordinates; the decorations library can be used to draw the zig-zag lines. A starting point (playing with my code and reading the TikZ documentation you can add the missing elements and customize the result):
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,decorations.pathmorphing}
\begin{document}
\begin{tikzpicture}[node distance=2cm]
% coordinates for the nodes
\coordinate (A) at (0,0);
\coordinate[above right = of A,label=$i^{\ast}$] (B);
\coordinate[right = 3cm of B,label=$i^{\ast}$] (C);
\coordinate[below right = of C] (D);
\coordinate[below right = of A] (E);
\coordinate[right = 3cm of E] (F);
% some straight lines uning the coordinates and adding labels
\draw (A) -- node[above] {$f^{\ast}$} (B) -- node[below,sloped,pos=0.25] {$\bar{v}=0$} node[below,sloped,pos=0.75] {$H^{-}$}
(F) -- (D);
\draw (A) -- (E) -- (C) -- (D);
% some decorated lines uning the coordinates and adding labels
\draw[decorate,decoration=zigzag] (B) -- node[above] {$r=0$} (C);
\draw[decorate,decoration=zigzag] (E) -- node[below] {$r=0$} (F);
\end{tikzpicture}
\end{document}
You have different possibilities. With some basic commands of tikz you can try this. I updated the first code . The final result is not complete but it's a good exercice to finish it by yourself.
Explanations
You have a lot of fine explanations in JLDIAZ's answer. I try to add some explanations to understand the difference between the codes.
Before drawing something, I like to know if I need to adapt the size of the picture with scale
for example. I prefer to avoid the positioning library
if I need a scaling picture.
\draw
is a shorthand for \path[draw]
. It's possible to define a path
, to draw this path and to define, to draw at the same time some coordinates and nodes.
With the next code, I can use [scale=2]
but It's also interesting to define some variables like \myunit
(here 4 signifies 4 cm) with the \pgfmathsetmacro command
.
Then it's impossible to draw with one path this sort of graphs. The first path begins with
\draw (0,0)
and it ends with cycle;
.
When you add a new coordinate (relative or absolute) you can add to the path nodes
.
As you can see the code is very simple,but you need to know why sometimes you need to use coordinate
or sometimes node
. coordinate
is a special node with some different parameters.
After --++(45:\myunit)
I get a line between the origine (45:\myunit)
is polar coordinates. Now I can add some nodes between the two points.
- With
coordinate (a)
I named the last point - With
node [above]{$i^+$}
I placed a basic node above the last point - With
node[pos=.5, above left] {$\cal{J}^+$}
I placed a node above the middle of the line defined by the last points.
The last interesting possibility is used in the final path with
- `\draw ... node[above=6pt] {$r=0$} node[below=1 cm] {III}``
It's possible to place the node where you want with something like [below=1 cm]
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
\begin{document}
\begin{tikzpicture}%[scale=2]
\pgfmathsetmacro\myunit{4}
\draw (0,0) node [left] {$i^0$}
--++(45:\myunit) coordinate (a)
node[pos=.5, above left] {$\cal{J}^+$}
node[pos=.5, below, sloped] {$\bar{u}=\infty$}
node [above]{$i^+$}
--++(-45:2*\myunit) node[pos=.25, below, sloped] {$\bar{u}=0$}
coordinate (d)
node [below]{$i^-$}
--++(45:\myunit) node [right]{$i^0$}
--++(135:\myunit) coordinate (b)
node [above]{$i^+$}
--++(-135:2*\myunit) coordinate (c)
node [below]{$i^-$}
--cycle;
\draw [decorate, decoration=zigzag] (a) -- node[above=6pt] {$r=0$}
node[below=1 cm] {III}
(b)
(c) -- (d);
\end{tikzpicture}
\end{document}