Make lens aperture in Tikz

A little late, but the following defines a pic that is more or less configurable (and I promptly used it to create an animation). The calculations are most likely inefficient and the overall code doesn't look as good as those posted by the usual TikZ experts.

\documentclass[tikz]{standalone}

\tikzset
  {
    ,aperture segments/.initial = 6
    ,aperture radius/.initial = 3
    ,aperture closed/.initial = .5
    ,aperture/.pic={
      \begin{scope}
        \pgfkeysgetvalue{/tikz/aperture segments}\segments
        \pgfkeysgetvalue{/tikz/aperture radius}\rad
        \pgfkeysgetvalue{/tikz/aperture closed}\closed
        \pgfmathsetmacro\ang{360/\segments}
        \pgfmathsetmacro\endang{360-\ang}
        \pgfmathsetmacro\alphtild{(180-\ang)/2}
        \pgfmathsetmacro\rp{(1-\closed)*\rad}
        \pgfmathsetmacro\cc{\rad*sqrt(2*(1-cos(\ang)))}
        \pgfmathsetmacro\bp{sqrt(\rad*\rad+\rp*\rp-2*\rad*\rp*cos(\ang))}
        \pgfmathsetmacro\alphprim{asin(\rp/\bp*sin(\ang))}
        \pgfmathsetmacro\alph{\alphtild-\alphprim}
        \pgfmathsetmacro\bet{180-\ang-\alph}
        \pgfmathsetmacro\bb{\cc*sin(\bet)/sin(\ang)}
        \foreach \r in {0,\ang,...,\endang}
          {
            \filldraw[fill = black!80, draw = white, thick, rotate = \r]
              (0:\rad) ++(180-\alphprim:\bb) -- (0:\rad)
              arc[start angle=0, end angle=\ang, radius=\rad]
              -- cycle;
          }%
      \end{scope}%
    }
  }

\begin{document}
\foreach\x in {0,0.025,...,1}
  {
    \begin{tikzpicture}
      \pic [aperture segments=9, aperture closed=\x] {aperture};
    \end{tikzpicture}
  }
\foreach\x in {1,0.975,...,0}
  {
    \begin{tikzpicture}
      \pic [aperture segments=9, aperture closed=\x] {aperture};
    \end{tikzpicture}
  }
\end{document}

enter image description here

A small document which describes what is calculated above and why:

\documentclass[]{article}

\title{Aperture drawing}
\author{Skillmon}
\date{}

\usepackage{tikz}
\usepackage[]{amsmath}
\usepackage{array}
\usepackage{collcell}
\usepackage{booktabs}
\usepackage{siunitx}

\newcolumntype\mathcol[1]{>{\startmath}#1<{\endmath}}
\let\startmath\(
\let\endmath\)
\newcolumntype\macrocol[1]{>{\collectcell\makemacroname}#1<{\endcollectcell}}
\newcommand\makemacroname[1]
  {%
    \texttt{\expandafter\string\csname #1\endcsname}%
  }

\begin{document}
\maketitle

The geometry we use is shown in figure~\ref{fig:geom}.
In the equations below variables correspond to the names in the used
Ti\textit{k}Z code to draw the aperture. The correspondences are shown in
table~\ref{tab:corres}. In the following I don't care about the sign of the
angles denoted with $\angle P_1P_2P_3$ and always only care for their absolute
value, so $\angle P_1P_2P_3$ might actually be $\angle P_3P_2P_1$.

\begin{figure}
  \centering
  \begin{tikzpicture}
    \def\segments{9}
    \def\rad{3}
    \def\closed{0.3}
    \pgfmathsetmacro\ang{360/\segments}
    \pgfmathsetmacro\endang{360-\ang}
    \pgfmathsetmacro\alphtild{(180-\ang)/2}
    \pgfmathsetmacro\rp{(1-\closed)*\rad}
    \pgfmathsetmacro\cc{\rad*sqrt(2*(1-cos(\ang)))}
    \pgfmathsetmacro\bp{sqrt(\rad*\rad+\rp*\rp-2*\rad*\rp*cos(\ang))}
    \pgfmathsetmacro\alphprim{asin(\rp/\bp*sin(\ang))}
    \pgfmathsetmacro\alph{\alphtild-\alphprim}
    \pgfmathsetmacro\bet{180-\ang-\alph}
    \pgfmathsetmacro\bb{\cc*sin(\bet)/sin(\ang)}
    \draw 
      (0,0)       coordinate(O) circle [radius=1.5pt] node [below]{$O$}
      (0:\rad)    coordinate(A) circle [radius=1.5pt] node [below right]{$A$}
      ++(180-\alphprim:\bb)
                  coordinate(C) circle [radius=1.5pt] node [above left]{$C$}
      (\ang:\rad) coordinate(B) circle [radius=1.5pt] node [above right]{$B$}
      (\ang:\rp)  coordinate(D) circle [radius=1.5pt] node [below]{$D$}
      ;
    \draw[blue]
      (A) arc[start angle=0, end angle=40, radius=3cm] -- (C) -- cycle;
    \draw[gray, dashed]
      (O) -- (A)
      (A) -- (B)
      (O) -- (B)
      ;
  \end{tikzpicture}
  \caption
    {%
      The geometry in which we want to calculate the position of point $C$%
      \label{fig:geom}%
    }
\end{figure}

\begin{table}
  \centering
  \begin{tabular}{\mathcol{c} \macrocol{l} \mathcol{l}}
    \toprule
    \multicolumn{1}{l}{Variable} & \multicolumn{1}{l}{Macro name}
      & \multicolumn{1}{l}{Meaning} \\
    \midrule
    \bar{p} & closed & \overline{DB}/\overline{OB} \\
    n & segments \\
    r & rad & \overline{OA}=\overline{OB} \\
    \gamma & ang & \angle AOB \\
    \tilde{\alpha} & alphtild & \angle OAB \\
    r_p & rp & \overline{OD} \\
    c & cc & \overline{BA} \\
    b_p & bp & \overline{AD} \\
    \alpha' & alphprim & \angle OAC \\
    \alpha & alph & \angle CAB \\
    \beta & bet & \angle ABC \\
    b & bb & \overline{AC} \\
    \bottomrule
  \end{tabular}
  \caption
    {%
      Variable-Macro-Correspondence and their geometrical meaning in
      figure~\ref{fig:geom}.%
      \label{tab:corres}%
    }
\end{table}

The variables we know the values of are $n$, $r$, and $\bar{p}$. $\bar{p}$ is in
the range $[0,1]$ and describes how closed the aperture is. $n$ is the number of
aperture segments and $r$ is the outer radius of the aperture. From $n$ we get
the angle $\gamma = \angle AOB$ straight forward:

\begin{equation}
  \gamma = \frac{\ang{360}}{n}
\end{equation}
Also relatively easy to calculate are the value of $p$ and $r_p$:
\begin{align}
  p &= 1 - \bar{p} \\
  r_p &= rp
\end{align}
The next thing we want to know is the angle $\angle ACB$. We know how many edges
the polygon of the aperture will have ($n$), so we know the sum
of internal angles and $\angle ACB$ is the adjacent angle of one of the internal
angles:
\begin{equation}
  \angle ACB = \ang{180} - \ang{180}  \frac{(n - 2)}{n}
    = \ang{180} \cdot (1 - 1 + \frac{2}{n}) = \frac{\ang{360}}{n} = \gamma
\end{equation}
The distances $c$ and $b_p$ can be calculated using the law of cosines:
\begin{align}
  c &= \sqrt{2r^2 - 2r^2\cos \gamma} = r \sqrt{2(1-\cos\gamma)} \\
  b_p &= \sqrt{r^2 + r_p^2 - 2rr_p\cos\gamma} \label{eq:bp}
\end{align}
We could further simplify eq.~\ref{eq:bp}, but this should suffice.
$\tilde{\alpha}$ can be calculated with the sum of internal angles in the
triangle $OAB$ since it is isosceles. With the sine theorem we can calculate
$\alpha'$ and therefore $\alpha$ and $\beta$:
\begin{align}
  \tilde{\alpha} &= \frac{\ang{180}-\gamma}{2} \\
  \alpha' &= \arcsin ( \frac{r_p}{b_p}\sin\gamma ) \\
  \alpha &= \tilde{\alpha} - \alpha' \\
  \beta &= \ang{180} - \gamma - \alpha
\end{align}
Using the sine theorem again we calculate the value of $b$ and with the position
of $A$ and the angle $\alpha'$ we get the position of $C$:
\begin{equation}
  b = c \frac{\sin\beta}{\sin\gamma}
\end{equation}
In Ti\textit{k}Z the point $C$ is now positioned at
\verb|(0:\rad) ++(180-\alphprim:\bb)|. Now we can draw our aperture segments.
\end{document}

You could draw triangles instead of rectangles:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
  \clip (0,0) circle (1);
  \foreach \r in {0,40,...,320}
    \fill[black!80,rotate=\r] (-0.5,1) -- (-0.5,-0.13) --++ (130:1) -- cycle;
\end{tikzpicture}
\end{document}

enter image description here

Tags:

Tikz Pgf