49

A Reuleaux triangle is a shape of constant width sort of like a rounded equilateral triangle.

Reuleaux Triangle from Wikipedia

(Reuleaux triangle - Wikipedia, the free encyclopedia)

It can be formed by the intersection of three circles like in a three set Venn diagram.

Reuleaux Triangle from MathWorld

(Reuleaux Triangle -- from Wolfram MathWorld)

What is the best way to draw a Reuleaux triangle using TikZ, Asymptote, or some language that is embeddable into LaTeX? Perhaps by drawing the three circles of a Venn diagram and cutting off the rest?

Thruston
  • 42,268

12 Answers12

34

Here is a small Metapost function to draw a general Reuleaux polygon. Explanations below.

prologues := 3;
outputtemplate := "%j%c.eps";

vardef reuleaux(expr n) = 
  for t=0 step 360/n until 359:
    1/2 up rotated t { left rotated (t+90/n) } .. { left rotated (t+270/n)} 
  endfor cycle enddef;

beginfig(1);
for i := 3 step 2 until 9:
  draw reuleaux(i) scaled 40i withcolor .6 red withpen pencircle scaled 1;
  draw fullcircle  scaled 40i withcolor .6 white;
endfor
endfig;    
end.

Scale, rotate, shift as required. It's sized so that it fits inside a fullcircle scaled to the same amount. enter image description here

Each corner is a point of the path, so if you want to join the vertices, join points 0, 1, ..., n-1; if you want the mid-points of each arc, use points 1/2, 3/2, ..., n-1/2, like this:

beginfig(2);
path t[];
for n := 3 upto 7:
  t[n] = reuleaux(n) scaled 60 shifted (75n,0);
  fill t[n] withcolor red+0.75green+0.2blue;
  draw for i = 0 upto n-1: point i     of t[n] -- endfor cycle withcolor .6 red;
  draw for i = 0 upto n-1: point i+1/2 of t[n] -- endfor cycle withcolor .6 blue;
endfor
endfig;

enter image description here

Obviously, you also could pick out points to label as well.

beginfig(3);
path t; t = reuleaux(3) scaled 90;
draw t withcolor .6 red;
dotlabel.top (btex $A$ etex, point 0 of t);
dotlabel.llft(btex $B$ etex, point 1 of t);
dotlabel.lrt (btex $C$ etex, point 2 of t);
endfig;

Labelled Reuleaux triangle

Explanations

I've revised this answer a couple of times, as I thought about the problem a bit more. The original versions used buildcycle and the pre-defined circular paths, but they are not really needed. The final version here is a simple and correct as I can make it.

The reuleaux(n) function returns a path with n vertices connected by circular arcs, whose radius is the length of the longest diagonal of the corresponding regular polygon.

To understand what it does, consider first the following function that returns the path of a regular polygon with n vertices:

vardef polygon(expr n) = 
  for t=0 step 360/n until 359:
    up rotated t -- 
  endfor cycle enddef;

up expands to (0,1), so with n=3 this function expands to

(0,1) -- (-0.866,-0.5) -- (0.866,-0.5) -- cycle

as required for a 3-sided regular polygon fitting inside a circle of unit radius. In Metapost however the predfined fullcircle path has unit diameter so for consistency it would be better to scale our polygon down by 1/2,

vardef polygon(expr n) = 
  for t=0 step 360/n until 359:
    1/2 up rotated t -- 
  endfor cycle enddef;

The precedence rules in MP mean that 1/2 up expands to (0,0.5) which is what we want.

Now we have a regular polygon that fits inside a fullcircle and to make it into a Reuleaux polygon we have to bend the straight lines into arcs centred on the opposite vertex (or the mid-point of the opposite vertices when n is even). We can do this using the path direction notation, and changing -- into .. to allow the path to bend.

vardef reuleaux(expr n) = 
  for t=0 step 360/n until 359:
    1/2 up rotated t { left rotated (t+90/n) } .. { left rotated (t+270/n)} 
  endfor cycle enddef;

Since left is up rotated 90, the required directions are given by the formulae shown, as you can work out with a little elementary geometry:

Some elementary geometry

If you want to convince yourself that the resulting arcs really are circular and have the right centres then draw appropriately scaled and shifted circles on top. The radius of such a circle would be the length of the longest diagonal on the polygon - AC in the figure above - which you can find with length (point (n+1)/2 of r - point 0 of r) where r=reuleaux(n).

Applications

The Reuleaux triangle features in some traditional geometric patterns, like this one:

Traditional geometric tiling

which we can draw like this: (if there's a better way to do the tiling, please comment!)

beginfig(6);
  path t, ring; s := 10; 
  t = reuleaux(3) scaled s;
  ring = for i=0 upto 5: subpath(-1,1) of t shifted (0,s) rotated (i*60) .. endfor cycle;
  pair offset;
  for i=0 upto 5:
    dx := 0;
    for j=0 upto 13:
      offset := (3*s,0) rotated (30*(j mod 2*2-1));
      dx := dx + xpart offset;
      dy := 3*i*s + 1/2 ypart offset;
      draw ring shifted (dx,dy) withcolor (.5,.7,.9);
    endfor
  endfor
endfig;

This may form the basis for other explorations. For example just changing the definition of t to t = reuleaux(2) scaled s produced this rather wonderful pattern.

enter image description here

Variations

If you want a Reuleaux polygon pointing right instead of up, then you just have to swap up and left in the definition for right and up.

vardef reuleaux(expr n) = 
  for t=0 step 360/n until 359:
    1/2 right rotated t { up rotated (t+90/n) } .. { up rotated (t+270/n)} 
  endfor cycle enddef;

beginfig(7);
  for n=3 upto 7:
     draw fullcircle  scaled 60 shifted (75n,0) withcolor .8 white;
     draw reuleaux(n) scaled 60 shifted (75n,0) withcolor .67 red;
  endfor
endfig;

This is slightly more consistent with plain MP as point 0 of these shapes corresponds to zero degrees rotation. They look like this:

enter image description here

We can also swap the two directions in the definition to produce what might be called anti-Reuleaux polygons.

vardef antireuleaux(expr n) = 
  for t=0 step 360/n until 359:
    1/2 right rotated t { up rotated (t+270/n) } .. { up rotated (t+90/n)} 
  endfor cycle enddef;

enter image description here

As you can see below, these anti-shapes are similar to, but subtly differ from, hypocycloid curves.

vardef hypocycloid(expr k) = 
  for t=0 step 1 until 360:
    point 0 of (fullcircle scaled (1/k) rotated (-t*k) 
                     shifted (1/2 right scaled (1-1/k))) rotated t --
  endfor cycle
enddef;

enter image description here

It is also possible to round the corners of a Reuleaux polygon while still retaining the constant width property. Here is a function to produce a rounded shape that takes a slightly more generalized approach. The first parameter is the number of sides, the second is the radius of the rounded corners as a fraction of the width.

vardef polygon(expr n) = 
  for t=0 step 360/n until 359:
    1/2 right rotated t -- 
  endfor cycle 
enddef;

vardef rounded_reuleaux(expr n, s) = 
  save m, a, b, p; m := (n+1)/2;
  pair a,b; path p; p := polygon(n); 
  for i = 0 upto n-1:
    hide(
      a := point i   of p - point i+m of p; 
      b := point i+1 of p - point i+m of p;
    )
    point i   of p + s*unitvector(a) { up rotated angle a } .. 
    point i+1 of p + s*unitvector(b) { up rotated angle b } ..
  endfor cycle
enddef;

beginfig(8);
for n := 3 upto 7:
   fill rounded_reuleaux(n,1/6) scaled 60 shifted (85n,0) withcolor (1/2,3/4,5/6);
   draw reuleaux(n)             scaled 60 shifted (85n,0);
endfor

enter image description here

Thruston
  • 42,268
  • What means : shifted (1/2 up rotated -theta). Especially up. – Tarass Feb 15 '14 at 17:46
  • 1
    up is standard MP short hand for the vector (0,1); 1/2 up expands to (0,0.5); (1/2 up rotated -theta) expands to (-0.5*sin(-theta),+0.5*cos(-theta)) which is where I want the centre of that part of the arc. – Thruston Feb 15 '14 at 18:07
  • ... but it's easier to write rotated than to remember the sin and cos formulae – Thruston Feb 15 '14 at 18:11
  • 1
    Your buildycle-based way of doing is, I think, the most general and appropriate up to now to solve this problem. Wish I had thought about it! – Franck Pastor Feb 16 '14 at 09:14
  • @Thruston, would you mind explaining how this is compiled: is there any preamble? Thanks! – PatrickT Feb 16 '14 at 16:54
  • 2
    @PatrickT no preamble needed, you just need the five lines that define the reuleaux function -it's all plain Metapost. Follow the first link for basic info about running MP. I';ll have some time tmw to tidy this up and add some explanations. – Thruston Feb 16 '14 at 23:10
  • @Thruston, thanks, you know I hadn't actually noticed the link to Metafont in your answer -- that's a great place to start, thanks! – PatrickT Feb 16 '14 at 23:17
  • @fpast I don't think they are rigorous, but over short angular distances like these they look ok to me. Your example is a good one, but Knuth himself (METAFONT book, p.70) notes that "at least 4 points are needed to get a path that is convincingly round". See also the discussion about circles and polygons (the subject of John Hobby's dissertation) on pp.148-9. However there's nothing inherently more circular about makepath pencircle which is how fullcircle is defined. – Thruston Feb 17 '14 at 18:39
  • Well, after a bit of search, it seems in fact that it is impossible to rigorously represent circular arcs with quadratic or cubic Bézier curves, but I see your point: it is indeed possible to obtain pretty good approximations of them. – Franck Pastor Feb 17 '14 at 19:04
  • By the way, the example I gave before I delete my previous comment was: beginfig(1); u:=5cm; draw u*right{up} .. {down}left*u; draw halfcircle scaled 2u withcolor red; endfig; end. It shows the rough approximation of a half circle of radius u=5cm by the cubic Bézier curve u*right{up} .. {down}left*u computed by MetaPost. – Franck Pastor Feb 17 '14 at 21:04
30

Another TikZ solution, but this time, TikZ does all the job. You just provide two coordinates (two of the vertices of the equilateral triangle) and the other vertex and the radii are automatically calculated. For example, the image below was produced using

\Reuleaux{0,0}{2,0}
\Reuleaux[Dandelion]{0,0}{3,-2}

The code:

\documentclass[dvipsnames]{article}
\usepackage{tikz}
\usetikzlibrary{intersections,positioning,calc}

\newcommand\Reuleaux[3][Aquamarine]{%
\def\A{#2}
\def\B{#3}
\begin{tikzpicture}
\begin{scope}
\clip[name path global=c1] (\A) 
  let
  \p1 = ($ (\B) - (\A) $)
  in
  circle ({veclen(\x1,\y1)});
\clip[name path global=c2] (\B) 
  let
  \p1 = ($ (\B) - (\A) $)
  in
  circle ({veclen(\x1,\y1)});
\clip[name path global=c3] ($ (\A) ! .5 ! (\B) ! {sin(60)*2} ! 90:(\B) $) 
  let
  \p1 = ($ (\B) - (\A) $)
  in
  circle ({veclen(\x1,\y1)});
\fill[#1] (current bounding box.north west) rectangle (current bounding box.south east);
\end{scope}
\draw (\A) 
  let
  \p1 = ($ (\B) - (\A) $)
  in
  circle ({veclen(\x1,\y1)});
\draw (\B) 
  let
  \p1 = ($ (\B) - (\A) $)
  in
  circle ({veclen(\x1,\y1)});
\draw ($ (\A) ! .5 ! (\B) ! {sin(60)*2} ! 90:(\B) $) 
  let
  \p1 = ($ (\B) - (\A) $)
  in
  circle ({veclen(\x1,\y1)});
\fill [name intersections={of=c1 and c2,by={a,b}}]
  (a) circle (2pt) node[label=above:$A$] {};
\fill [name intersections={of=c2 and c3,by={c,d}}]
  (d) circle (2pt) node[label=left:$B$] {};
\fill [name intersections={of=c3 and c1,by={e,f}}]
  (f) circle (2pt) node[label=right:$C$] {};
\draw (a) -- (d) -- (f) -- cycle;
\end{tikzpicture}%
}

\begin{document}

\Reuleaux{0,0}{2,0}

\Reuleaux[Dandelion]{0,0}{3,-2}

\end{document}

enter image description here

If only the triangle is to be produced, the \draw commands can be suppressed from the above code:

\documentclass[dvipsnames]{article}
\usepackage{tikz}
\usetikzlibrary{intersections,positioning,calc}

\newcommand\Reuleaux[3][Aquamarine]{%
\def\A{#2}
\def\B{#3}
\begin{tikzpicture}
\begin{scope}
\clip[name path global=c1] (\A) 
  let
  \p1 = ($ (\B) - (\A) $)
  in
  circle ({veclen(\x1,\y1)});
\clip[name path global=c2] (\B) 
  let
  \p1 = ($ (\B) - (\A) $)
  in
  circle ({veclen(\x1,\y1)});
\clip[name path global=c3] ($ (\A) ! .5 ! (\B) ! {sin(60)*2} ! 90:(\B) $) 
  let
  \p1 = ($ (\B) - (\A) $)
  in
  circle ({veclen(\x1,\y1)});
\fill[#1] (current bounding box.north west) rectangle (current bounding box.south east);
\end{scope}
\fill [name intersections={of=c1 and c2,by={a,b}}]
  (a) circle (2pt) node[label=above:$A$] {};
\fill [name intersections={of=c2 and c3,by={c,d}}]
  (d) circle (2pt) node[label=left:$B$] {};
\fill [name intersections={of=c3 and c1,by={e,f}}]
  (f) circle (2pt) node[label=right:$C$] {};
\draw (a) -- (d) -- (f) -- cycle;
\end{tikzpicture}%
}

\begin{document}

\Reuleaux{0,0}{2,0}

\Reuleaux[Dandelion]{0,0}{3,-2}

\Reuleaux[Maroon]{-2,-2}{0,0}

\end{document}

enter image description here

Gonzalo Medina
  • 505,128
25

With tkz-euclide

\documentclass{scrartcl}
\usepackage{tkz-euclide}
\usetkzobj{all}

\begin{document}
  \begin{tikzpicture}
    \tkzDefPoint(0,0){A}
    \tkzDefPoint(5,0){B}
    \tkzDefEquilateral(A,B)\tkzGetPoint{C}
    \tkzDrawPolygon[red](A,B,C)
    \tkzDrawArc[fill=gray!20](A,B)(C)
    \tkzDrawArc[fill=gray!20](B,C)(A)
    \tkzDrawArc[fill=gray!20](C,A)(B)
  \end{tikzpicture}
\end{document}

enter image description here

With

  \begin{tikzpicture}
    \tkzDefPoint(0,0){A}
    \tkzDefPoint(5,0){B}
    \tkzDefEquilateral(A,B)\tkzGetPoint{C}
    \tkzDrawPolygon[red](A,B,C)
    \begin{scope}
        \tkzSetUpLine[style=dashed,color=gray]
        \tkzDrawCircle(B,C)
        \tkzDrawCircle(A,B)
        \tkzDrawCircle(C,A)
    \end{scope}
    \tkzDrawArc[fill=gray!20](A,B)(C)
    \tkzDrawArc[fill=gray!20](B,C)(A)
    \tkzDrawArc[fill=gray!20](C,A)(B)
    \end{tikzpicture}

enter image description here

And finally

\documentclass{scrartcl}
\usepackage{tkz-euclide}
\usetkzobj{all}

\begin{document}
  \begin{tikzpicture}
    \tkzDefPoint(0,0){A}
    \tkzDefPoint(5,0){B}
    \tkzDefEquilateral(A,B)\tkzGetPoint{C}
    \tkzFillSector[fill=gray!20](A,B)(C)
    \tkzFillSector[fill=gray!20](B,C)(A)
    \tkzFillSector[fill=gray!20](C,A)(B)
  \end{tikzpicture}   
\end{document}

enter image description here

Remark : It's possible to create a macro with the last code.

Annexe : With tikz a minimum code is (based on Mark Wibrow's answer)

 \documentclass[tikz,border=5]{standalone}
   \begin{document}
    \tikz\draw[fill=blue!20] (0,0)
    \foreach \i in {1,2,3}{ arc (\i*120:\i*120+60:4)} ;
  \end{document}

enter image description here

Alain Matthes
  • 95,075
24

Just for typing exercise with PSTricks.

\documentclass[pstricks,border=16pt]{standalone}
\usepackage{pst-eucl}
\usepackage{fp}
\FPset\R{5}
\FPeval\T{tan(pi/3)*R/2}
\FPeval\B{T-R}

\begin{document}
\begin{pspicture}(0,\B)(\R,\T)
    \pstGeonode[PosAngle={-90,-90,45},CurveType=polygon]{A}(\R,0){B}(!\R\space 2 div \T){C}
    \foreach \x/\y/\z in {A/B/C,B/C/A,C/A/B}{\pstArcOAB{\x}{\y}{\z}}
\end{pspicture}
\end{document}

enter image description here

Edit

It is too short for typing exercise. It takes 183 characters.

% with PSTricks  by me.
\documentclass[pstricks]{standalone}
\begin{document}
\pspicture(6,5)
\pscustom{\moveto(5,1)\psLoop{3}{\rmoveto(-4,0)\psarc(!!CP){4}{0}{60}\rotate{120}}}
\endpspicture
\end{document}

enter image description here

Mark Wibrow's solution below takes 196 characters. I won. :-)

% with Tikz by Mark Wibrow
\documentclass[tikz,border=5]{standalone}
\begin{document}
\tikz\draw (90:1) \foreach \i in {1,2,3}{ [rotate=\i*120] arc (0:60:2*cos 30) } -- cycle 
 -- (210:1) -- (330:1) -- cycle;
\end{document}
21

Based on percusse's suggestion, but implemented in Asymptote and requiring no angle calculations. The key is the function arc(c, a, b), which returns an arc centered at c from a to b. (If there is no such arc, then it returns an arc centered at c from a to the line c--b.)

Note also the use of the & operator for concatenating two paths with a common endpoint.

\documentclass[margin=10pt]{standalone}
\usepackage{asymptote}
\begin{document}
\begin{asy}
unitsize(3cm);
path triangle = scale(1/2)*polygon(3);
pair a = point(triangle, 0), b=point(triangle,1), c=point(triangle,2);
path releaux = arc(c=a, b, c) & arc(c=b, c, a) & arc(c=c, a, b) & cycle;
fill(releaux, gray);
draw(releaux);
\end{asy}
\end{document}

The result:

  • in golfcode style: size(3cm); path t=polygon(3); pair a = point(t, 0), b=point(t,1), c=point(t,2); path releaux = arc(c=a, b, c) & arc(c=b, c, a) & arc(c=c, a, b) & cycle; filldraw(releaux, gray); – Black Mild Jan 22 '21 at 09:45
17

Here is an attempt with intersetions library:

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{intersections}
\begin{document}
  \begin{tikzpicture}
    \path[use as bounding box] (0.1,0.1) rectangle (2,1.5);
    \clip (0,0) circle (2cm);
    \clip (1,2) circle (2cm);
    \clip (2,0) circle (2cm);
    \draw[thick,fill=blue!20!green!20,name path=left] (0,0) circle (2cm);
    \draw[thick,name path=right] (2,0) circle (2cm);
    \draw[thick,name path=top] (1,2) circle (2cm);     
    \path [name intersections={of=left and right, by=a},name intersections={of=left and top, by=b},name intersections={of=top and right, by=c}]
[fill=blue!30,draw=orange] (a) -- node[left,text=black]{\footnotesize$r$}(b) -- node[above,text=black]{\footnotesize$r$}(c) -- node[right,text=black]{\footnotesize$r$}cycle;
  \end{tikzpicture}
\end{document}

enter image description here

To colour only the reuleaux triangle comment the following lines in the above code:

    %\path [name intersections={of=left and right, by=a},name intersections={of=left and top, by=b},name intersections={of=top and right, by=c}]
%[fill=blue!30,draw=orange] (a) -- node[left,text=black]{\footnotesize$r$}(b) -- node[above,text=black]{\footnotesize$r$}(c) -- node[right,text=black]{\footnotesize$r$}cycle;
  \end{tikzpicture}

enter image description here

Employing Gonzalo's suggestion of using equilateral triangle, here is an attempt.

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{backgrounds}
\begin{document}
  \begin{tikzpicture}
    \coordinate (a) at (0,0);
    \coordinate (b) at (60:1cm);
    \coordinate (c) at (0:1cm);
    \node[fill,circle,inner sep=1pt] at (a) {};
    \node[fill,circle,inner sep=1pt] at (b) {};
    \node[fill,circle,inner sep=1pt] at (c) {};
    \begin{pgfonlayer}{background}
    \path[use as bounding box] (0.1,0.1) rectangle (1,0.6);
    \clip (a) circle (1cm);
    \clip (b) circle (1cm);
    \clip (c) circle (1cm);
    \draw[thick,fill=blue!20!green!20] (a) circle (1cm);
    \draw[thick] (b) circle (1cm);
    \draw[thick] (c) circle (1cm);
    \end{pgfonlayer}    
  \end{tikzpicture}
\end{document}

I have used background layer just to get the circles at the corners un-clipped.

enter image description here

15

It's pretty easy with PSTricks and pst-eucl:

\documentclass[a4paper,10pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}%
\usepackage{lmodern}

\usepackage[svgnames, pdf]{pstricks}%[]
\usepackage{pst-eucl}

\pagestyle{empty}
\begin{document}

\begin{pspicture*}(-5,-5)(5,5)
\pstTriangle(4 ; 60){A}(0,0){B}(4,0){C}
\pscustom[fillstyle = solid, fillcolor = LightSteelBlue!30!White , linecolor = Navy]{%
\pstArcOAB{A}{B}{C}
\pstArcOAB{B}{C}{A}
\pstArcOAB{C}{A}{B}}
\pspolygon[linecolor = red](A)(B)(C)
\end{pspicture*}

\end{document} 

output

This code can be compiled directly with pdflatex --enable-write18.

Bernard
  • 271,350
15

No frills...

\documentclass[tikz,border=5]{standalone}
\begin{document}
\tikz\draw(0,1)\foreach\i in{1,2,3}{[rotate=\i*120]arc(0:60:sqrt 3)}--cycle--(210:1)--(330:1)--cycle;
\end{document}

enter image description here

or

\documentclass[tikz,border=5]{standalone}
\begin{document}
\tikz\fill[even odd rule] (90:1) \foreach \i in {1,2,3}{ [rotate=\i*120] arc (0:60:2*cos 30) } -- cycle 
  -- (210:1) -- (330:1) -- cycle;
\end{document}

enter image description here

Mark Wibrow
  • 70,437
13

Another try with MetaPost. Heavily inspired by Charles Staat's proposition and Gonzalo Medina's presentation (and much less ingenious than Thruston's program). The challenge for me was to create the arc(a, b, c) macro of Asymptote, used by Charles Staat, and which doesn't exist in Plain MetaPost nor Metafun, macro "which returns an arc centered at c from a to b. (If there is no such arc, then it returns an arc centered at c from a to the line c--b.)"

First version using Enrico Gregorio's great gmp package as (PDF)LaTeX interface for MetaPost (the shell-escape option must be activated).

\documentclass[12pt]{scrartcl}
\usepackage[latex, shellescape]{gmp}
\gmpoptions{everymp={%
  input mpcolornames; 
  input latexmp;
    setupLaTeXMP(options="12pt", mode=rerun);
  % 
  u := 1cm; % scale
  %
  vardef arc(expr a, b, c) =
    save r, myhalfcircle, radius; 
    numeric r; r = abs(b-a);
    path myhalfcircle, radius;
    myhalfcircle := halfcircle scaled abs(2r) rotated angle(b-a) shifted a;
    radius = a -- max(1.1, 1.1r/abs(c-a))[a,c];
    if myhalfcircle intersectiontimes radius <> (-1,-1): myhalfcircle 
    else: myhalfcircle reflectedabout (a, b)  fi cutafter radius
  enddef;
  %
  vardef Reuleaux(expr A, B, my_color) =
    save C, Reuleaux_triangle;
    pair C; C := B rotatedaround(A, 60);
    path Reuleaux_triangle; 
    Reuleaux_triangle = arc(A, B, C) -- arc(B, C, A) -- arc(C, A, B) -- cycle;
    fill Reuleaux_triangle withcolor my_color; draw Reuleaux_triangle; 
    draw A--B--C--cycle;
    freelabeloffset:=2bp;
    freelabel(textext("$A$"), A, 0.5[B,C]);
    freelabel(textext("$B$"), B, 0.5[A,C]);
    freelabel(textext("$C$"), C, 0.5[A,B]);
  enddef;}}

\begin{document}
\begin{mpost*}[mpmem=metafun]
  Reuleaux(origin, (3u, 2u), Orange);
\end{mpost*}
%
\begin{center}
  \begin{mpost*}[mpmem=metafun]
    Reuleaux(origin, (4u, 0), green);
  \end{mpost*}
\end{center}

\bigskip
\begin{flushright}
  \begin{mpost*}[mpmem=metafun]
    Reuleaux((-2u, -3u), (0.5u, 3u), 0.8white);
  \end{mpost*}
\end{flushright}
\end{document}

Reuleaux triangles with gmp

The second version (with the same output) is to be typesetted with LuaLaTeX, since it makes use of the latest available version of the luamplib package.

\documentclass[12pt]{scrartcl}
\usepackage{luamplib}
  \mplibsetformat{metafun}
  \everymplib{verbatimtex \leavevmode etex;
    input mpcolornames; 
    u := 1cm; % scale

    vardef arc(expr a, b, c) =
      save r, myhalfcircle, radius; 
      numeric r; r = abs(b-a);
      path myhalfcircle, radius;
      myhalfcircle := halfcircle scaled abs(2r) rotated angle(b-a) shifted a;
      radius = a -- max(1.1, 1.1r/abs(c-a))[a,c];
      if myhalfcircle intersectiontimes radius <> (-1,-1): myhalfcircle 
      else: myhalfcircle reflectedabout (a, b)  fi cutafter radius
    enddef;


    vardef Reuleaux(expr A, B, my_color) =
      save C, Reuleaux_triangle;
      pair C; C := B rotatedaround(A, 60);
      path Reuleaux_triangle; 
      Reuleaux_triangle = arc(A, B, C) -- arc(B, C, A) -- arc(C, A, B) -- cycle;
      fill Reuleaux_triangle withcolor my_color; draw Reuleaux_triangle; 
      draw A--B--C--cycle;
      freelabeloffset:=2bp;
      freelabel(textext("$A$"), A, 0.5[B,C]);
      freelabel(textext("$B$"), B, 0.5[A,C]);
      freelabel(textext("$C$"), C, 0.5[A,B]);
    enddef;

    beginfig(1);}
  \everyendmplib{endfig;}

\begin{document}
  \begin{mplibcode}
    Reuleaux(origin, (3u, 2u), Orange);
  \end{mplibcode}
   %
  \begin{center}
    \begin{mplibcode}
      Reuleaux(origin, (4u, 0), green);
    \end{mplibcode}
  \end{center}

  \bigskip
  \begin{flushright}
    \begin{mplibcode}
      Reuleaux((-2u, -3u), (0.5u, 3u), 0.8white);
    \end{mplibcode}
  \end{flushright}
\end{document}

Franck Pastor
  • 18,756
12

Here is the new \reuleauxpolypath macro. It inserts into a TikZ path the closed path associated with a Reuleaux polygon. The current point of the path is the center of the polygon. Its three arguments are :

  1. the initial direction to position the first vertex,

  2. the radius of the Reuleaux polygon (distance between the center and a vertex or radius of the circumscribed circle),

  3. the number of vertex.

\newcommand\reuleauxpolypath[3]{% initial direction, radius, num vertex
  \pgfextra{
    \pgfmathsetmacro\ang{360/(#3)}
    \pgfmathsetmacro\semiang{\ang/2}
    \pgfmathsetmacro\semisemiang{\ang/4}
    \pgfmathsetmacro\radius{(1+cos(\semiang))/cos(\semisemiang)*(#2)}
  } ++({(#1)}:{#2}) \foreach \num in {1,...,#3}{
        arc [start angle={(#1)+(\num-1)*\ang+\semisemiang},
             delta angle=\semiang,radius=\radius pt]
  } -- cycle
}

Example:

\draw (0,0) \reuleauxpolypath{0}{1cm}{3};

enter image description here

A complete example:

enter image description here

\documentclass[tikz]{standalone}
\newcommand\reuleauxpolypath[3]{% initial direction, radius, num vertex
  \pgfextra{
    \pgfmathsetmacro\ang{360/(#3)}
    \pgfmathsetmacro\semiang{\ang/2}
    \pgfmathsetmacro\semisemiang{\ang/4}
    \pgfmathsetmacro\radius{(1+cos(\semiang))/cos(\semisemiang)*(#2)}
  } ++({(#1)}:{#2}) \foreach \num in {1,...,#3}{
    arc [start angle={(#1)+(\num-1)*\ang+\semisemiang},delta angle=\semiang,radius=\radius pt]
  } -- cycle
}
\begin{document}
\begin{tikzpicture}
  \foreach \num/\col in {3/red,5/blue,7/green}{
    \draw[draw=\col] (0,0) \reuleauxpolypath{0}{1cm}{\num};
  }
  \fill[draw=red,fill=orange] (0,2.5) \reuleauxpolypath{90}{1cm}{5};
\end{tikzpicture}
\end{document}
Paul Gaborit
  • 70,770
  • 10
  • 176
  • 283
7

Another variant with only tikz. In this answer, I created a macro to draw the triangle based on two points.

\documentclass[11pt]{scrartcl}
\PassOptionsToPackage{dvipsnames,svgnames}{xcolor} 
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\newcommand\reuleaux[2]{% we need two points, it's possible to modify that ...
 \pgfextra{\pgfmathanglebetweenpoints{%
 \pgfpointanchor{#1}{center}}{%
 \pgfpointanchor{#2}{center}}
 \pgfmathsetmacro{\@initialdirection}{\pgfmathresult}}
 let \p1 = ($ (#1) - (#2) $) in  (#2) 
   arc (\@initialdirection:\@initialdirection+60:{veclen(\x1,\y1)})
   arc (\@initialdirection +120:\@initialdirection +180:{veclen(\x1,\y1)}) 
   arc (\@initialdirection +240:\@initialdirection +300:{veclen(\x1,\y1)})}
\makeatother

\begin{document}

\begin{tikzpicture}
 \path (0,0)   coordinate (A)
       (5,2)   coordinate (B)
       (8,-2)  coordinate (C)
       (10,1)  coordinate (D);

 \draw[fill=MidnightBlue!20] \reuleaux{A}{B} ;
 \draw[fill=green!20] \reuleaux{D}{C} ;
\end{tikzpicture}

\end{document}

enter image description here

Alain Matthes
  • 95,075
6

Another solution, using my xpicture package.

First of all, we note that radius $r$ of every circular arc equals the side of the triangle; if this triangle is inscribed in a circle of radius 1, using the cosine law, it is easy to see that $r^2=2(1-\cos(120))$. Then, all we have to do is to draw a circular arc of radius $r$ and amplitude 60 degrees from every corner.

\documentclass{article}
\usepackage{xpicture}

\begin{document}

% Calcule the radius, using calculator functions
\DEGREESCOS{120}{\temp}
\SUBTRACT{1}{\temp}{\temp}
\MULTIPLY{2}{\temp}{\temp}
\SQRT{\temp}{\radius}    

\setlength{\unitlength}{1cm}
\begin{Picture}(-1,-1)(1,1)
   \polarreference
   \degreesangles

   \Polygon(1,90)(1,210)(1,330)           

   \Put(1,90){\circularArc{\radius}{240}{300}}
   \Put(1,210){\circularArc{\radius}{0}{60}}
   \Put(1,330){\circularArc{\radius}{120}{180}}
\end{Picture}
\end{document}

enter image description here