# Use tikz (for example) to draw pictures in hyperbolic geometry

I would like to draw pictures in the Poincaré disk model for hyperbolic geometry. Are there any built-in or add-on packages for tikz to do this? For example, it would be nice to have functions for drawing Saccheri quadrilaterals or Lambert quadrilaterals or asymptotic triangles.

(In my brief use so far, the tkz-euclide package looks very good for Euclidean geometry, and now I'm looking for a hyperbolic analogue of it.)

## 6 Answers

Here's another TikZ solution. Given two points on the Poincare plane or disc, it draws the geodesic between them. It does this by defining a (complicated!) to path which works out the circle and angles and then draws the correct arc. It has some basic error checking to see if it ought to draw a straight line, but it checks for the exact condition rather than to within the precision of TeX so if your points are almost one above the other (or on the same radius) so that to all intents and purposes the geodesic is straight then this code might not detect that in time and end up dividing by something smaller than it should (as it is, I had to be careful how I broke up the calculations as some methods gave Big Numbers at partial stages).

\documentclass{article}
\thispagestyle{empty}
\usepackage{tikz}

\makeatletter

\def\hyper@x#1,#2\relax{#1}
\def\hyper@y#1,#2\relax{#2}
\def\hyper@coords#1{#1}

\newif\ifhyper@vertical

\def\hyper@computer#1#2{%
\edef\hyper@toscan{(#1)}
\tikz@scan@one@point\hyper@coords\hyper@toscan
\edef\hyper@sx{\the\pgf@x}
\edef\hyper@sy{\the\pgf@y}
\edef\hyper@toscan{(#2)}
\tikz@scan@one@point\hyper@coords\hyper@toscan
\edef\hyper@ex{\the\pgf@x}
\edef\hyper@ey{\the\pgf@y}
\pgfmathsetmacro{\hyper@mx}{(\hyper@ex + \hyper@sx)/2}
\pgfmathsetmacro{\hyper@my}{(\hyper@ey + \hyper@sy)/2}
\pgfmathsetmacro{\hyper@dx}{\hyper@ex - \hyper@sx}
\pgfmathparse{\hyper@dx == 0 ? "\noexpand\hyper@verticaltrue" : "\noexpand\hyper@verticalfalse"}
\pgfmathresult
\ifhyper@vertical
\edef\hyper@cmd{-- (\tikztotarget)}
\else
\pgfmathsetmacro{\hyper@dy}{\hyper@ey - \hyper@sy}
\pgfmathsetmacro{\hyper@t}{\hyper@my/\hyper@dx}
\pgfmathsetmacro{\hyper@cx}{\hyper@mx + \hyper@t * \hyper@dy}
\pgfmathsetmacro{\hyper@radius}{veclen(\hyper@cx - \hyper@sx, \hyper@sy)}
\pgfmathsetmacro{\hyper@sangle}{180 - atan2(\hyper@cx-\hyper@sx,\hyper@sy)}
\pgfmathsetmacro{\hyper@eangle}{180 - atan2(\hyper@cx-\hyper@ex,\hyper@ey)}
\edef\hyper@cmd{arc[radius=\hyper@radius pt, start angle=\hyper@sangle, end angle=\hyper@eangle]}
\fi
}

\def\hyper@disc@computer#1#2{%
\edef\hyper@toscan{(#1)}
\tikz@scan@one@point\hyper@coords\hyper@toscan
\edef\hyper@sx{\the\pgf@x}
\edef\hyper@sy{\the\pgf@y}
\edef\hyper@toscan{(#2)}
\tikz@scan@one@point\hyper@coords\hyper@toscan
\edef\hyper@ex{\the\pgf@x}
\edef\hyper@ey{\the\pgf@y}
\pgfmathsetmacro{\hyper@det}{\hyper@sx * \hyper@ey - \hyper@sy * \hyper@ex}
\pgfmathparse{\hyper@det == 0 ? "\noexpand\hyper@verticaltrue" : "\noexpand\hyper@verticalfalse"}
\pgfmathresult
\ifhyper@vertical
\edef\hyper@cmd{-- (\tikztotarget)}
\else
\pgfmathsetmacro{\hyper@mx}{(\hyper@ex + \hyper@sx)/2}
\pgfmathsetmacro{\hyper@my}{(\hyper@ey + \hyper@sy)/2}
\pgfmathsetmacro{\hyper@dx}{\hyper@ex - \hyper@sx}
\pgfmathsetmacro{\hyper@dy}{\hyper@ey - \hyper@sy}
\pgfmathsetmacro{\hyper@dradius}{\pgfkeysvalueof{/tikz/hyperbolic disc radius}}
\pgfmathsetmacro{\hyper@t}{(\hyper@dradius^2 - \hyper@sx * \hyper@ex - \hyper@sy * \hyper@ey)/(2 * (\hyper@sx * \hyper@ey - \hyper@sy * \hyper@ex))}
\pgfmathsetmacro{\hyper@radius}{sqrt(\hyper@t^2 + .25) * veclen(\hyper@dx,\hyper@dy)}
\pgfmathsetmacro{\hyper@cx}{\hyper@mx + \hyper@t * \hyper@dy}
\pgfmathsetmacro{\hyper@cy}{\hyper@my - \hyper@t * \hyper@dx}
\pgfmathsetmacro{\hyper@sangle}{atan2(\hyper@sx-\hyper@cx,\hyper@sy - \hyper@cy)}
\pgfmathsetmacro{\hyper@eangle}{atan2(\hyper@ex-\hyper@cx,\hyper@ey - \hyper@cy)}
\pgfmathsetmacro{\hyper@eangle}{\hyper@eangle > \hyper@sangle + 180 ? \hyper@eangle - 360 : \hyper@eangle}
\edef\hyper@cmd{arc[radius=\hyper@radius pt, start angle=\hyper@sangle, end angle=\hyper@eangle]}
\fi
}

\tikzset{%
hyperbolic disc radius/.initial={1cm},
hyperbolic plane/.style={
to path={
\pgfextra{\hyper@computer\tikztostart\tikztotarget}
\hyper@cmd
}
},
hyperbolic disc/.style={
to path={
\pgfextra{\hyper@disc@computer\tikztostart\tikztotarget}
\hyper@cmd
}
}
}

\makeatother
\begin{document}
\begin{tikzpicture}[every to/.style={hyperbolic plane}]
\fill[blue] (0,1) \foreach \k in {0,...,7} { to ++(\k * 45:2)};
\coordinate (b) at (1,2);
\coordinate (a) at (3,4);
\fill (a) circle[radius=2pt];
\fill (b) circle[radius=2pt];
\draw (-2,0) -- (6,0);
\draw (a) to (b);
\end{tikzpicture}
\begin{tikzpicture}[hyperbolic disc radius=2cm,
every to/.style={hyperbolic disc}]
\draw (0,0) circle[radius=\pgfkeysvalueof{/tikz/hyperbolic disc radius}];
\pgfmathsetmacro{\hyperrad}{1/(2*sin(22.5))}
\fill[blue] (-112.5:\hyperrad) \foreach \k in {0,...,7} { to ++(\k * 45:1)};
\coordinate (b) at (1.2,.3);
\coordinate (a) at (.8,-.4);
\fill (a) circle[radius=2pt];
\fill (b) circle[radius=2pt];
\draw (a) to (b);
\end{tikzpicture}
\end{document}


Result: One extension that would be nice would be to be able to draw an arc from a point starting in a particular direction and going on for a particular length. A hyperbolic version of the Euclidean \draw (1,0) -- ++(45:2);.

• I've figured out how to do that last bit for the plane. Now I've just the disc to do. I haven't done actual computations in geometry for years! – Loop Space May 28 '11 at 18:01

Here is very basic solution. It get (some of) the job done. The use of \hgline should be obvious from the examples. Feel free to suggest improvements.

\documentclass[]{minimal}
\usepackage{tikz}

\begin{document}

\newcommand{\hgline}{
\pgfmathsetmacro{\thetaone}{#1}
\pgfmathsetmacro{\thetatwo}{#2}
\pgfmathsetmacro{\theta}{(\thetaone+\thetatwo)/2}
\pgfmathsetmacro{\phi}{abs(\thetaone-\thetatwo)/2}
\pgfmathsetmacro{\close}{less(abs(\phi-90),0.0001)}
\ifdim \close pt = 1pt
\draw[blue] (\theta+180:1) -- (\theta:1);
\else
\pgfmathsetmacro{\R}{tan(\phi)}
\pgfmathsetmacro{\distance}{sqrt(1+\R^2)}
\draw[blue] (\theta:\distance) circle (\R);
\fi
}

\begin{tikzpicture}
\draw (0,0) circle (1);
\clip (0,0) circle (1);
\hgline{30}{-30}
\hgline{180}{270}
\hgline{30}{120}
\hgline{0}{180}

\end{tikzpicture}

\end{document}


The result is • Great answer - I have added an improvement with my answer below (too much code for a comment), so that the when there is an angle >=180 between the two input angles, the geodesics still are drawn. – Jānis Lazovskis Mar 26 '17 at 17:30

Here is an example of using tkz-euklide to draw a hyperbolic line through two given points:

\documentclass{article}
\usepackage{tkz-euclide}

\begin{document}
\begin{tikzpicture}[scale=3]
\tkzDefPoint(0,0){O}
\tkzDefPoint(1,0){A}
\tkzDrawCircle(O,A)
\tkzDefPoint(0.3,-0.25){z1}
\tkzDefPoint(-0.5,-0.5){z2}
\tkzClipCircle(O,A)
\tkzDrawCircle[orthogonal through=z1 and z2](O,A)
\tkzDrawPoints[color=black,fill=red,size=12](z1,z2)
\tkzLabelPoints(z1,z2)
\end{tikzpicture}
\end{document}


The result looks like this: • I didn't know about the "orthogonal" argument to \tkzDrawCircle. Is there actually a manual for tkz-euclide, or just a large collection of examples? Anyway, this looks like a nice approach. – John Palmieri Apr 27 '11 at 18:45
• Never mind, I just found the manual (on CTAN, but not apparently on the original tkz-euclide web site). – John Palmieri Apr 27 '11 at 18:55

Probably not. I googled "latex hyperbolic geometry" and the top hit was this page. There are plenty of papers about hyperbolic geometry written in latex but no packages that I found for hyperbolic geometry.

But I think these things can be done in TikZ, if one works hard enough.

• I agree. Furthermore, drawing Saccheri and Lambert quadrilaterals seem quite simple in TikZ. – ipavlic Apr 26 '11 at 8:00
• I agree that it's pretty easy to draw a Saccheri quadrilateral, for example, but I don't think it's a one-liner. Marking the appropriate angles as right angles seems trickier. In any case, I was hoping someone else had already done the hard work, so I wouldn't have to... – John Palmieri Apr 26 '11 at 16:59
• @John Palmieri: It may not be so hard since there are Euclidean constructions of the non-Euclidean lines. Given points A and B in the Poincare disk, the center of the (Euclidean) circle which is the (hyperbolic) line between them has center at the intersection of the perpendicular bisector to the (Euclidean) line segment AB and the boundary circle. So you can code it up in tkz-euclide. – Matthew Leingang Apr 26 '11 at 19:18
• @Matthew: Are you sure about that? Geodesics should be orthogonal to the boundary circle, and the way I read your description, I don't see why those circles should be orthogonal. – Jan Hlavacek Apr 26 '11 at 22:20
• @Matthew: It is true in the upper half plane model. The problem is that while the Moebius transformation that takes the upper half plane to the circle maps circles and lines to circles and lines, it does not map centers to centers. – Jan Hlavacek Apr 27 '11 at 12:18

kind of what you are looking for, i hope it helps. its not in euclidean though

\documentclass[a4paper]{article}
\usepackage{tikz}
....
\begin{tikzpicture}
\draw[black,thick] (0,1.5) -- (0,0) -- (3,0) -- (3,1.5); %the rectangle part
\draw [black, thick] plot [smooth, tension=2] coordinates {(0,1.5)(1.5,1)(3,1.5)};%smooth curve top that follows these lines
\end{tikzpicture}


this is what it looks like Improving on the answer of @Frederic to still draw the arcs when there is an angle >=180, even >360, between the two input angles. The only change is in the \ifdim loop, where an extra condition is added.

\newcommand{\hgline}{
\pgfmathsetmacro{\thetaone}{mod(#1,360)}
\pgfmathsetmacro{\thetatwo}{mod(#2,360)}
\pgfmathsetmacro{\theta}{(\thetaone+\thetatwo)/2}
\pgfmathsetmacro{\phi}{abs(\thetaone-\thetatwo)/2}
\pgfmathsetmacro{\close}{less(abs(\phi-90),0.0001)}
\ifdim \close pt = 1pt
\draw[blue] (\thetaone:1) -- (\thetatwo:1);
\else
\pgfmathsetmacro{\R}{tan(\phi)}
\ifdim \R pt < 0pt
\pgfmathsetmacro{\distance}{sqrt(1+\R*\R)}
\draw[blue] (\theta:-\distance) circle (\R);
\else \ifdim \R pt > 0pt
\pgfmathsetmacro{\distance}{sqrt(1+\R^2)}
\draw[blue] (\theta:\distance) circle (\R);
\fi
\fi
\fi
}


First, if the angles are 180 degrees apart, the straight line drawn is directly in between them. Second, if the angles are more than 180 degrees apart, there is a catch that draws the correct circle. I also noticed that \R^2 is negative if \R is negative, whereas \R*\R is not. For example, drawing the circle, clipping, and giving the command \foreach \a in {120,130,...,300}{\hgline{\a}{30}} gives the following result: 