It does seem, as Caramdir says in the comments, that the ideal way to do this would be to separate the drawing from the filling and do all of the drawing first and then the filling afterwards. I don't think that this is doable as a single preexisting command, but where there's a TeX there's a TikZ, as the saying goes. Here's a way that works by using layers.
Edit: Using the technique in "Z-level" in TikZ it is now possible to collapse the commands a little so that there's no need to introduce a new high-level command. (Original solution left in for comparison.) Caramdir's solution is probably the simplest when it is possible to give all the paths in a single command. If that is not (for some reason) possible, the following is more adaptable.
\documentclass{standalone}
% \url{https://tex.stackexchange.com/q/11512/86}
\usepackage{tikz}
\pgfdeclarelayer{back}
\pgfsetlayers{back,main}
\def\drawfill#1;{
\fill[gray!30] #1;
\begin{pgfonlayer}{back}
\draw[line width=2pt] #1;
\end{pgfonlayer}}
\tikzset{%
on layer/.code={
\pgfonlayer{#1}\begingroup
\aftergroup\endpgfonlayer
\aftergroup\endgroup
},%
draw on back/.style={
preaction={
draw,
on layer=back,
line width=2pt
},
gray!30
}
}
\begin{document}
\begin{tikzpicture}
\drawfill ( 0.0, 0.0) circle (1cm and 0.5cm);
\drawfill ( 0.4, 0.5) circle (0.3cm);
\drawfill (-0.4, -0.5) circle (0.3cm);
\drawfill (-0.4, 0.4) circle (0.3cm);
\drawfill ( 0.4, -0.4) circle (0.3cm);
\draw[] (0,0) node {Q.M.};
\begin{scope}[yshift=-2cm]
\fill[draw on back] ( 0.0, 0.0) circle (1cm and 0.5cm);
\fill[draw on back] ( 0.4, 0.5) circle (0.3cm);
\fill[draw on back] (-0.4, -0.5) circle (0.3cm);
\fill[draw on back] (-0.4, 0.4) circle (0.3cm);
\fill[draw on back] ( 0.4, -0.4) circle (0.3cm);
\draw[] (0,0) node {Q.M.};
\end{scope}
\end{tikzpicture}
\end{document}
Notice the extra large line width since half of the line width gets covered by the fills.
I feel that the other answers given are perhaps a little overcomplicated! If you want the triangle exact then maybe they are the best way to go. But if you want something that just looks about right, then there is a much simpler way to do this using ordinary fadings.
(Added in edit: I've updated this a little to try to correct the colour bias. The red colour is now correct and the green/blue are relatively correct. That is, the green and blue are correct at the bottom of the triangle, but as you move up the sides then some blue gets mixed in with the green and vice-versa. However, before it gets too noticeable, the red swamps the picture so it's actually quite close to the Real Thing.)
Here's the result:
Here's the code:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fadings}
\begin{document}
\begin{tikzpicture}
\fill[green] (90:4) -- (210:4) -- (-30:4) -- cycle;
\fill[blue,path fading=west] (90:4) -- (210:4) -- (-30:4) -- cycle;
\fill[red,path fading=south] (90:4) -- (210:4) -- (-30:4) -- cycle;
\end{tikzpicture}
\end{document}
Best Answer
Here is a small Metapost function to draw a general Reuleaux polygon. Explanations below.
Scale, rotate, shift as required. It's sized so that it fits inside a
fullcircle
scaled to the same amount.Each corner is a
point
of the path, so if you want to join the vertices, join points0, 1, ..., n-1
; if you want the mid-points of each arc, use points1/2, 3/2, ..., n-1/2
, like this:Obviously, you also could pick out points to label as well.
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 apath
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:
up
expands to(0,1)
, so with n=3 this function expands toas 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,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.Since
left
isup rotated 90
, the required directions are given by the formulae shown, as you can work out with a little 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)
wherer=reuleaux(n)
.Applications
The Reuleaux triangle features in some traditional geometric patterns, like this one:
which we can draw like this: (if there's a better way to do the tiling, please comment!)
This may form the basis for other explorations. For example just changing the definition of
t
tot = reuleaux(2) scaled s
produced this rather wonderful pattern.Variations
If you want a Reuleaux polygon pointing right instead of up, then you just have to swap
up
andleft
in the definition forright
andup
.This is slightly more consistent with plain MP as point 0 of these shapes corresponds to zero degrees rotation. They look like this:
We can also swap the two directions in the definition to produce what might be called anti-Reuleaux polygons.
As you can see below, these anti-shapes are similar to, but subtly differ from, hypocycloid curves.
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.