
% LTeX: language=en

% gears: draw intermeshing system of gears
%
% Originally written by Maxime Chupin <maxime.chupin@tuta.com>,
% 2026.
%
% Distributed under the terms of the GNU free documentation licence:
%   http://www.gnu.org/licenses/fdl.html
% without any invariant section or cover text.

\documentclass[english]{ltxdoc}

\input{mp-gears-preamble.tex}

\usepackage[english]{babel}

\makeindex[title=Command Index, columns=2]



%\lstset{moredelim=*[s][\color{red}\rmfamily\itshape]{<}{>}}
%\lstset{moredelim=*[s][\color{blue}\rmfamily\itshape]{<<}{>>}}

\begin{document}

\title{{\mpgears}: drawing systems of intermeshing gears with \MP}
\author{Maxime Chupin, \url{maxime.chupin@tuta.com}}
\date{\gearsDate}

%% === Page de garde ===================================================
\thispagestyle{empty}
\begin{tikzpicture}[remember picture, overlay]
  \node[below right, shift={(-4pt,4pt)}] at (current page.north west) {%
    \includegraphics{fond.pdf}%
  };
\end{tikzpicture}%

\noindent
{\Huge \mpgears}\par\bigskip
\noindent
{\Large  drawing systems of intermeshing gears \\[0.2cm]with \hologo{METAPOST}}\\[1cm]
\parbox{0.6\textwidth}{
  \begin{mplibcode}[mpgears]
    input gears;
    input geom2d-svgnames
    
beginfig(1);
    setUnit(0.3cm);
    (G[3],G[4]) = buildExternalGearPair(40,12,0.5,20,(0,0),0,20);
    drawGear(G3,LightBlue,"clockwork");
    drawGear(G4,PeachPuff,"classical");
endfig;
  \end{mplibcode}%
}\hfill
\parbox{0.6\textwidth}{\Large\raggedleft
  \textbf{Contributor}\\
  Maxime \textsc{Chupin}\\
  \url{maxime.chupin@tuta.com}
}
\vfill
\begin{center}
  Version \gearsVersion, \gearsDate \\
  \url{https://gitlab.gutenberg-asso.fr/mchupin/mp-gears}
\end{center}
%% == Page de garde ====================================================
\newpage

%\maketitle

\begin{abstract}
  This \hologo{METAPOST} package allows to draw system of intermeshing gears.
\end{abstract}


\begin{center}
  \url{https://gitlab.gutenberg-asso.fr/mchupin/mp-gears}
\end{center}

\tableofcontents



\bigskip

\begin{tcolorbox}[ arc=0pt,outer arc=0pt,
  colback=darkred!3,
  colframe=darkred,
  breakable,
  boxsep=0pt,left=5pt,right=5pt,top=5pt,bottom=5pt, bottomtitle =
  3pt, toptitle=3pt,
  boxrule=0pt,bottomrule=0.5pt,toprule=0.5pt, toprule at break =
  0pt, bottomrule at break = 0pt,]
  \itshape
  This package is in beta version---do not hesitate to report bugs, as well as requests for improvement.
\end{tcolorbox}

\section{Introduction}

This package therefore allows users to model various gears and gear systems (and
even spirographs). In what follows, we will assume that the reader is familiar
with key concepts in gear design, such as the base radius, pitch radius, module,
pressure angle, pitch, etc. 

For further references, please
see~\cite{cuisinier,chevasson,chevalier,wikipedia_gear,zpag}. 

There is the excellent \package{pst-gears} package~\cite{pst-gears} by Manuel
Luque and Hebert Voss, which served as a major source of inspiration for me.
However, I believe that \hologo{METAPOST}~\cite{metapost} is a language
particularly well-suited to the construction of gear systems and that it may
offer a bit more flexibility. 

Because with \hologo{METAPOST}, we do not need to declare \typeMP{numeric}
variable, with \mpgears, we define parameters (in table) associated to un
\typeMP{numeric} identifier and then we manipulate the \emph{gear} object with
this \typeMP{numeric} identifier. 

\begin{tcolorbox}[ arc=0pt,outer arc=0pt,
  colback=darkred!3,
  colframe=darkred,
  breakable,
  boxsep=0pt,left=5pt,right=5pt,top=5pt,bottom=5pt, bottomtitle =
  3pt, toptitle=3pt,
  boxrule=0pt,bottomrule=0.5pt,toprule=0.5pt, toprule at break =
  0pt, bottomrule at break = 0pt,]
  \itshape
  This package and its documentation are developed without any use of generative
  artificial intelligence: noGIA. 
\end{tcolorbox}


\section{Installation}

\mpgears is on \ctan{} and can also be installed via the package manager of your
distribution.

\begin{center}
  \url{https://www.ctan.org/pkg/mp-gears}
\end{center}


\subsection{With \TeX live under Linux or macOS}

To install \mpgears with \TeX Live, you will have to create the directory
\lstinline+texmf+  in your \lstinline+home+. 

\begin{commandshell}
mkdir ~/texmf
\end{commandshell}

Then, you will have to place the \lstinline+gears.mp+  files in 
\begin{center}
  \lstinline+~/texmf/metapost/mp-gears/+
\end{center}


Once this is done, \mpgears will be loaded with the classic \MP{}
input code
\begin{mpcode}
input gears
\end{mpcode}

\subsection{With Mik\TeX{} and Windows}

These two systems are unknown to the author of \mpgears, so we
refer you to the Mik\TeX documentation concerning the addition of local packages:
\begin{center}
  \url{http://docs.miktex.org/manual/localadditions.html}
\end{center}

\section{Building Gears}

In this section, we present the building macros. These macros define the
parameters of the gears, and return \emph{identifiers} to which the parameters
are attached. Hence, these functions do not produce any drawing. However, in
order to help the readers to understand, we will use \emph{drawing macros}
without presenting them. For details about them, see section~\ref{sec:drawing}.
\subsection{External Gears}

The first command is for building one gear. \mpgears offer three kinds of gear,
\emph{external}, \emph{internal} and \emph{rack}. We start with the first case,
more classical. For the second kind, see sectio~\ref{sec:internal}, and the
third case is described in section~\ref{sec:rack}.  

\begin{colourband}
\commande|buildExternalGear(«Z1»,«m»,«a»,«c», «r»)|\return{\typeMP{numeric}}\smallskip\index{buildExternalGear@\lstinline+buildExternalGear+}
\begin{description}
  \item[\meta{Z1}:] \typeMP{numeric} number of teeth of the gear.
  \item[\meta{m}:] \typeMP{numeric} module of the gear.
  \item[\meta{a}:] \typeMP{numeric} pressure angle.
  \item[\meta{c}:] \typeMP{pair} center of the gear.
  \item[\meta{r}:] \typeMP{numeric} angle of rotation of the gear.
\end{description}
\end{colourband}

Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
A = buildExternalGear(16,0.5,20,(0,0),0);
drawGear(A,(0.7,0.3,0.3),"classical");
endfig;
\end{ExempleMP}


The next command is maybe more useful because it builds two enmeshed gears.   

\begin{colourband}
\commande|buildExternalGearPair(«Z1»,«Z2»,«m»,«a»,«c», «r», «ar»)|\return{\typeMP{pair}}\smallskip\index{buildExternalGearPair@\lstinline+buildExternalGearPair+}

This function builds two  intermeshed gears and give a \typeMP{pair} of 
identifiers. 
\begin{description}
  \item[\meta{Z1}:] \typeMP{numeric} number of teeth of the first gear.
  \item[\meta{Z2}:] \typeMP{numeric} number of teeth of the second gear.
  \item[\meta{m}:] \typeMP{numeric} module of the system.
  \item[\meta{a}:] \typeMP{numeric} pressure angle.
  \item[\meta{c}:] \typeMP{pair} center of the first gear.
  \item[\meta{r}:] \typeMP{numeric} angle of rotation of the first gear.
  The second gear will be rotated with the corresponded linked angle. 
  \item[\meta{ar}:] \typeMP{numeric} angle of rotation of the center
  of the second gear around the center of the first gear.
\end{description}
\end{colourband}

Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
(A1,A2) = buildExternalGearPair(16,10,0.5,20,(0,0),30,45);
drawGear(A1,(0.7,0.3,0.3),"classical");
drawGear(A2,(0.3,0.7,0.3),"classical");
endfig;
\end{ExempleMP}

You can also create a gear that needs to mesh with an existing one. To do this,
use the following macro. This macro also works if the existing gear is an
internal one (see section~\ref{sec:internal}).

\begin{colourband}
\commande|buildExternalGearFor(«id»,«Z2»,«ar»)|\return{\typeMP{numeric}}\smallskip\index{buildExternalGearFor@\lstinline+buildExternalGearFor+}
\begin{description}
  \item[\meta{id}:] \typeMP{numeric} identifier to the existing gear.
  \item[\meta{Z2}:] \typeMP{numeric} number of teeth of the new gear.
  \item[\meta{ar}:] \typeMP{numeric} angle of rotation of the center
  of the new gear around the center of the existing gear.
\end{description}
\end{colourband}

Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
(A1,A2) = buildExternalGearPair(16,10,0.5,20,(0,0),30,45);
A3 = buildExternalGearFor(A2,16,-20);
drawGear(A1,(0.7,0.3,0.3),"classical");
drawGear(A2,(0.3,0.7,0.3),"classical");
drawGear(A3,(0.3,0.3,0.7),"classical");
endfig;
\end{ExempleMP}

One can build an external gear compounded to another one in the sens that they
only  
share the same center (axis of rotation) and the same angle of rotation. 
\begin{colourband}
\commande|buildCompoundGear(«id»,«Za»,«m»,«a»)|\return{\typeMP{pair}}\smallskip\index{buildCompoundGear@\lstinline+buildCompoundGear+}

This function builds two  intermeshed gears and give a \typeMP{pair} of 
identifiers. 
\begin{description}
  \item[\meta{id}:] \typeMP{numeric} identifier to the existing gear.
  \item[\meta{Za}:] \typeMP{numeric} number of teeth of the new gear.
  \item[\meta{m}:] \typeMP{numeric} module of the new gear.
  \item[\meta{a}:] \typeMP{numeric} pressure angle of the new gear.
\end{description}
\end{colourband}

Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
A1 = buildExternalGear(16,0.5,20,(0,0),30);
A2 = buildCompoundGear(A1,22,0.2,14);
drawGear(A1,(0.7,0.3,0.3),"classical");
drawGear(A2,(0.3,0.7,0.3),"classical");
endfig;
\end{ExempleMP}


\subsection{Internal Gears}\label{sec:internal}

The equivalent macros exist for internal gear. Fist, the simpler one to build
only one internal gear. 

\begin{colourband}
\commande|buildInternalGear(«Z1»,«m»,«a»,«c», «r»)|\return{\typeMP{numeric}}\smallskip\index{buildInternalGear@\lstinline+buildInternalGear+}
\begin{description}
  \item[\meta{Z1}:] \typeMP{numeric} number of teeth of the gear.
  \item[\meta{m}:] \typeMP{numeric} module of the gear.
  \item[\meta{a}:] \typeMP{numeric} pressure angle.
  \item[\meta{c}:] \typeMP{pair} center of the gear.
  \item[\meta{r}:] \typeMP{numeric} angle of rotation of the gear.
\end{description}
\end{colourband}

Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
A = buildInternalGear(16,0.5,20,(0,0),0);
drawGear(A,(0.7,0.3,0.3),"classical");
endfig;
\end{ExempleMP}




Of course, you cannot mesh two
internal gears. Hence, the following macro build two gears, the first is an
internal one, and the second an external one.  

\begin{colourband}
\commande|buildInternalGearPair(«Z1»,«Z2»,«m»,«a»,«c», «r», «ar»)|\return{\typeMP{pair}}\smallskip\index{buildInternalGearPair@\lstinline+buildInternalGearPair+}

This function builds two  intermeshed gears and give a \typeMP{pair} of 
identifiers. 
\begin{description}
  \item[\meta{Z1}:] \typeMP{numeric} number of teeth of the first gear.
  \item[\meta{Z2}:] \typeMP{numeric} number of teeth of the second gear.
  \item[\meta{m}:] \typeMP{numeric} module of the system.
  \item[\meta{a}:] \typeMP{numeric} pressure angle.
  \item[\meta{c}:] \typeMP{pair} center of the first gear.
  \item[\meta{r}:] \typeMP{numeric} angle of rotation of the first gear.
  The second gear will be rotated with the corresponded linked angle. 
  \item[\meta{ar}:] \typeMP{numeric} angle of rotation of the center
  of the second gear around the center of the first gear.
\end{description}
\end{colourband}

Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
(A1,A2) = buildInternalGearPair(26,8,0.5,20,(0,0),40,45);
drawGear(A1,(0.7,0.3,0.3),"classical");
drawGear(A2,(0.3,0.7,0.3),"classical");
endfig;
\end{ExempleMP}

We can also build a internal gear meshed to an existing external one.


\begin{colourband}
\commande|buildInternalGearFor(«id»,«Z2»,«ar»)|\return{\typeMP{numeric}}\smallskip\index{buildInternalGearFor@\lstinline+buildInternalGearFor+}
\begin{description}
  \item[\meta{id}:] \typeMP{numeric} identifier to the existing gear.
  \item[\meta{Z2}:] \typeMP{numeric} number of teeth of the new gear.
  \item[\meta{ar}:] \typeMP{numeric} angle of rotation of the center
  of the new gear around the center of the existing gear.
\end{description}
\end{colourband}

Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
A = buildExternalGear(8,0.5,20,(0,0),0);
B = buildInternalGearFor(A,16,-20);
drawGear(A,(0.7,0.3,0.3),"classical");
drawGear(B,(0.3,0.7,0.3),"classical");
endfig;
\end{ExempleMP}

\subsection{Rack}\label{sec:rack}

There exist another kind of gear: rack. It can be viewed as an external gear
with infinite radius. Because of the singularity, we use another type of object,
distinct from internal and external gear. However, macros related to racks are
quite similar to the ones for internal and external gears. 

The rack is defined by default vertically. 

\begin{colourband}
\commande|buildRack(«Z1»,«m»,«a»,«c»,«r»,«t»)|\return{\typeMP{numeric}}\smallskip\index{buildRack@\lstinline+buildRack+}
\begin{description}
  \item[\meta{Z1}:] \typeMP{numeric} number of teeth of the rack. This should be
  odd and if the user chooses an even number, 1 is added. 
  \item[\meta{m}:] \typeMP{numeric} module of the rack.
  \item[\meta{a}:] \typeMP{numeric} pressure angle.
  \item[\meta{c}:] \typeMP{pair} center of the rack on the equivalent of the
  radius of an external gear (which becomes a line). It is on the middle of the
  middle tooth. 
  \item[\meta{r}:] \typeMP{numeric} angle of rotation of the rack around the center.
  \item[\meta{t}:] \typeMP{numeric} translation of the rack. 
\end{description}
\end{colourband}

Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
A = buildRack(5,0.5,20,(0,0),0,0);
drawRack(A,(0.7,0.3,0.3));
endfig;
\end{ExempleMP}

We can only mesh a rack with an external gear. This is done by the following
macro. 

\begin{colourband}
\commande|buildGearRackPair(«Z1»,«Z2»,«m»,«a»,«c», «r», «ar»)|\return{\typeMP{pair}}\smallskip\index{buildGearRackPair@\lstinline+buildGearRackPair+}

\begin{description}
  \item[\meta{Z1}:] \typeMP{numeric} number of teeth of the  gear.
  \item[\meta{Z2}:] \typeMP{numeric} number of teeth of the rack.
  \item[\meta{m}:] \typeMP{numeric} module of the system.
  \item[\meta{a}:] \typeMP{numeric} pressure angle.
  \item[\meta{c}:] \typeMP{pair} center of the gear.
  \item[\meta{r}:] \typeMP{numeric} angle of rotation of the gear.
  The rack will be \emph{translated} with the corresponded length. 
  \item[\meta{ar}:] \typeMP{numeric} angle of rotation of the center
  of the rack around the center of the gear.
\end{description}
\end{colourband}

Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
(A1,A2) = buildGearRackPair(16,7,0.5,20,(0,0),12,45);
drawGear(A1,(0.7,0.3,0.3),"classical");
drawRack(A2,(0.3,0.7,0.3));
endfig;
\end{ExempleMP}

Like the other kinds of gear, we can define a rack meshed with an existing
external gear. 

\begin{colourband}
\commande|buildRackFor(«id»,«Z2»,«ar»)|\return{\typeMP{numeric}}\smallskip\index{buildRackFor@\lstinline+buildRackFor+}
\begin{description}
  \item[\meta{id}:] \typeMP{numeric} identifier to the existing gear.
  \item[\meta{Z2}:] \typeMP{numeric} number of teeth of the rack.
  \item[\meta{ar}:] \typeMP{numeric} angle of rotation of the center
  of the rack around the center of the existing gear.
\end{description}
\end{colourband}


Here, a simple example.
\begin{ExempleMP}
input gears

beginfig(1);
(A1,A2) = buildGearRackPair(16,7,0.5,20,(0,0),12,45);
A3 = buildRackFor(A1,9,180+45);
drawGear(A1,(0.7,0.3,0.3),"classical");
drawRack(A2,(0.3,0.7,0.3));
drawRack(A3,(0.3,0.3,0.7));
endfig;
\end{ExempleMP}



\section{Drawing}\label{sec:drawing}

There is only one macro to draw a gear. Depending on the type of the gear, there
are several styles of drawing: three for external gear and one pour internal
gear. 

\subsection{Unit}

Drawings produced with \mpgears use an unit for $x$ and $y$ axis of
\hologo{METAPOST}. The default value is \SI{0.5}{cm}. To get the unit, you can
use the following macra.
\begin{colourband}
\commande|getUnit|\return{\typeMP{numeric}}\smallskip\index{getUnit@\lstinline+getUnit+}
\end{colourband}

To change the value of the \mpgears unit, you can use the following macro. 
\begin{colourband}
\commande|setUnit(«u»)|\smallskip\index{setUnit@\lstinline+setUnit+}
\begin{description}
  \item[\meta{u}]: \typeMP{numeric} the new value for \mpgears unit. 
\end{description}
\end{colourband}




\subsection{Gear and Rack}

\begin{colourband}
\commande|drawGear(«id»,«c»,«s»)|\smallskip\index{drawGear@\lstinline+drawGear+}
\begin{description}
  \item[\meta{id}:] \typeMP{numeric} identifier to the existing gear.
  \item[\meta{c}:] \typeMP{color} the color of the gear or \typeMP{string}
  \lstinline+"None"+. In the last case, the gear is not colored.
  \item[\meta{s}:] \typeMP{string} type of gear. \lstinline+"classical"+ for both
  internal and external gear, and \lstinline+"clockwork"+ and
  \lstinline+"spirograph"+ for external gear.
\end{description}
\end{colourband}

Because this macro produce a \typeMP{picture} and a code using the
\lstinline+draw+ \hologo{METAPOST} macro, it is possible to add any drawing
compatible \hologo{METAPOST} code at this end of it. For instance, because we
use \package{luamplib}~\cite{luamplib} for this documentation, we can the \pdf{}
transparency.

\begin{ExempleMP}
input gears

beginfig(1);
A = buildExternalGear(28,0.5,20,(0,0),0);
B = buildExternalGearFor(A,16,-20);
drawGear(A,(0.7,0.3,0.3),"clockwork") withtransparency(1,0.3);
drawGear(B,"None","classical");
endfig;
\end{ExempleMP}

When the \lstinline+"clockwork"+ style is used, the gear will be hollow if the
primitive radius is greater than three times the tooth height. Otherwise, the
gear will be solid, much like with the \lstinline+"classical"+  style.

For internal gear and rack, there is only one style of drawing. 

The \lstinline+"spirograph"+ type is illustrated in the following example.

\begin{ExempleMP}
input gears

beginfig(1);
A = buildExternalGear(12,0.5,20,(0,0),0);
drawGear(A,(0.7,0.3,0.3),"spirograph");
endfig;
\end{ExempleMP}

It comes with other macros to draw pictures produced by a spirograph. We refer
to section~\ref{sec:spirograph} for details.

For racks, we have a similar macro. 
\begin{colourband}
\commande|drawRack(«id»,«c»)|\smallskip\index{drawRack@\lstinline+drawRack+}
\begin{description}
  \item[\meta{id}:] \typeMP{numeric} identifier to the existing rack.
  \item[\meta{c}:] \typeMP{color} the color of the rack or \typeMP{string}
  \lstinline+"None"+. In the last case, the rack is not colored.
\end{description}
\end{colourband}


\subsection{Different Colors}

By default, lines are drawn with black color. You can change that using the
following command.

\begin{colourband}
\commande|setLineColor(«c»)|\smallskip\index{setLineColor@\lstinline+setLineColor+}
\begin{description}
  \item[\meta{c}]: \typeMP{color} the new value for line color. 
\end{description}
\end{colourband}

When the \lstinline+"classical"+ style is used, the axis and the key color are
drawn with respectively color \lstinline+(0.6,0.6,0.6)+ and 
\lstinline+(0.4,0.4,0.4)+. You can change that using the two following macros. 
\begin{colourband}
\commande|setAxisColor(«c»)|\smallskip\index{setAxisColor@\lstinline+setAxisColor+}
\begin{description}
  \item[\meta{c}]: \typeMP{color} the new value for axis color. 
\end{description}
\end{colourband}


\begin{colourband}
\commande|setKeyColor(«c»)|\smallskip\index{setKeyColor@\lstinline+setKeyColor+}
\begin{description}
  \item[\meta{c}]: \typeMP{color} the new value for key color. 
\end{description}
\end{colourband}

\section{Other Macros}

\subsection{Getting Parameters}

In this section, we list simple macros to get parameters of the gear or the
rack. Most of them do not need explanation. Once again, all the dimensions are
scaled by the \mpgears unit. 
\begin{colourband}
\commande|getPrimitiveRadius(«id»)|\return{\typeMP{numeric}}\smallskip\index{getPrimitiveRadius@\lstinline+getPrimitiveRadius+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear (rack does not have
  radius parameters). 
\end{description}
\end{colourband}

\begin{colourband}
\commande|getTopRadius(«id»)|\return{\typeMP{numeric}}\smallskip\index{getTopRadius@\lstinline+getTopRadius+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear (rack does not have
  radius parameters). 
\end{description}
\end{colourband}


\begin{colourband}
\commande|getBottomRadius(«id»)|\return{\typeMP{numeric} (in degree)}\smallskip\index{getBottomRadius@\lstinline+getBottomRadius+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear (rack does not have
  radius parameters). 
\end{description}
\end{colourband}


\begin{colourband}
\commande|getRadialPoint(«id»,«t»)|\return{\typeMP{pair}}\smallskip\index{getRadialPoint@\lstinline+getRadialPoint+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear (not rack).
  \item[\meta{t}:] \typeMP{numeric} between 0 and 1 to get the point
  $c+r(\cos(\theta),\sin(\theta))$ where $c$ is the center of the gear, $r$ is
  the primitive radius, and $\theta$ the angle of rotation.  
\end{description}
\end{colourband}
\label{com:radialPoint}
\begin{ExempleMP}
input gears
beginfig(1);
A = buildExternalGear(26,0.2,20,(0,0),45);
drawGear(A,"None","classical");
draw getCenter(A)--getRadialPoint(A,1) dashed evenly;
drawdot getRadialPoint(A,0.5) withpen pencircle scaled 2pt;
endfig;
\end{ExempleMP}



\begin{colourband}
\commande|getPressureAngle(«id»)|\return{\typeMP{numeric} (in degree)}\smallskip\index{getPressureAngle@\lstinline+getPressureAngle+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear or rack. 
\end{description}
\end{colourband}


\begin{colourband}
\commande|getModule(«id»)|\return{\typeMP{numeric}}\smallskip\index{getModule@\lstinline+getModule+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear or the rack. 
\end{description}
\end{colourband}


\begin{colourband}
\commande|getTeethNbr(«id»)|\return{\typeMP{numeric}}\smallskip\index{getTeethNbr@\lstinline+getTeethNbr+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear or the rack. 
\end{description}
\end{colourband}

\begin{colourband}
\commande|getPrimitivePitch(«id»)|\return{\typeMP{numeric}}\smallskip\index{getPrimitivePitch@\lstinline+getPrimitivePitch+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear or the rack. 
\end{description}
\end{colourband}


\begin{colourband}
\commande|getCenter(«id»)|\return{\typeMP{pair}}\smallskip\index{getCenter@\lstinline+getCenter+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear or the rack. For
  racks, the center is either in the middle tooth, or if it is meshed at the
  point of contact with the primitive radius of the gear.
\end{description}
\end{colourband}


\begin{colourband}
\commande|getToothHeight(«id»)|\return{\typeMP{numeric}}\smallskip\index{getToothHeight@\lstinline+getToothHeight+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear or the rack. 
\end{description}
\end{colourband}


\begin{colourband}
\commande|getRotation(«id»)|\return{\typeMP{numeric}}\smallskip\index{getRotation@\lstinline+getRotation+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear or the rack. 
\end{description}
\end{colourband}

\begin{colourband}
\commande|getTranslation(«id»)|\return{\typeMP{numeric}}\smallskip\index{getTranslation@\lstinline+getTranslation+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the  rack (gears do not have
  translation parameter). 
\end{description}
\end{colourband}

\subsection{Getting construction objects}

There are some macros that help to get the different construction circles and
lines (respectively for gears and racks).

\subsubsection{Circles}

Beware, these macros only work for gears.

\begin{colourband}
\commande|primitiveCircle(«id»)|\return{\typeMP{path}}\smallskip\index{primitiveCircle@\lstinline+primitiveCircle+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear. 
\end{description}
\end{colourband}

\begin{colourband}
\commande|baseCircle(«id»)|\return{\typeMP{path}}\smallskip\index{baseCircle@\lstinline+baseCircle+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear. 
\end{description}
\end{colourband}

\begin{colourband}
\commande|bottomCircle(«id»)|\return{\typeMP{path}}\smallskip\index{bottomCircle@\lstinline+bottomCircle+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear. 
\end{description}
\end{colourband}

\begin{colourband}
\commande|topCircle(«id»)|\return{\typeMP{path}}\smallskip\index{topCircle@\lstinline+topCircle+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the gear. 
\end{description}
\end{colourband}

Here, an example of use of these macros. 


\begin{ExempleMP}
input gears

beginfig(1);
A = buildExternalGear(24,0.5,20,(0,0),0);
drawGear(A,(0.7,0.3,0.3),"classical");
draw primitiveCircle(A) withpen pencircle scaled 1.5pt withcolor red;
draw baseCircle(A) dashed evenly  withcolor blue;
draw bottomCircle(A) dashed evenly  withcolor green;
draw topCircle(A) dashed evenly  withcolor green;
endfig;
\end{ExempleMP}

\subsubsection{Lines}

Beware, these macros are only for rack objects. 

\begin{colourband}
\commande|primitiveLine(«id»)|\return{\typeMP{path}}\smallskip\index{primitiveLine@\lstinline+primitiveLine+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the rack. 
\end{description}
\end{colourband}

\begin{colourband}
\commande|baseLine(«id»)|\return{\typeMP{path}}\smallskip\index{baseLine@\lstinline+baseLine+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the rack. 
\end{description}
\end{colourband}

\begin{colourband}
\commande|bottomLine(«id»)|\return{\typeMP{path}}\smallskip\index{bottomLine@\lstinline+bottomLine+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the rack. 
\end{description}
\end{colourband}

\begin{colourband}
\commande|topLine(«id»)|\return{\typeMP{path}}\smallskip\index{topLine@\lstinline+topLine+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the rack. 
\end{description}
\end{colourband}

\begin{ExempleMP}
input gears

beginfig(1);
  (Q,P) = buildGearRackPair(27,10,0.5,20,(0,0),-15,157);
  drawGear(Q,"None","classical") withpen pencircle scaled 1pt;
  drawRack(P,"None") withpen pencircle scaled 1pt;
  drawdot getCenter(P) withpen pencircle scaled 2pt;
  draw primitiveLine(P);
  draw baseLine(P) dashed evenly;
  draw bottomLine(P) dashed evenly;
  draw topLine(P) dashed evenly;
  draw primitiveCircle(Q);
  draw baseCircle(Q) dashed evenly;
  draw bottomCircle(Q) dashed evenly;
  draw topCircle(Q) dashed evenly;
endfig;
\end{ExempleMP}

\subsection{Spirograph}\label{sec:spirograph}

\mpgears provides a number of macros for creating Spirograph illustrations. The
building of a \emph{spirograph} gear compute points along the Archimedes spiral.
We can get these points using the following macros. The number of such points
will depend on the radius of the external gear. 

\begin{colourband}
\commande|getSpirographPointNbr(«id»)|\return{\typeMP{numeric}}\smallskip\index{getSpirographPointNbr@\lstinline+getSpirographPointNbr+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the external gear. 
\end{description}
\end{colourband}


\begin{colourband}
\commande|getSpirographPoint(«id»,«n»)|\return{\typeMP{numeric}}\smallskip\index{getSpirographPoint@\lstinline+getSpirographPoint+}
\begin{description}
  \item[\meta{id}]: \typeMP{numeric} identifier of the external gear.
  \item[\meta{n}:] \typeMP{numeric}, integer between 0 and \lstinline+getSpirographPointNbr(+\meta{id}\lstinline+)+.  
\end{description}
\end{colourband}

Thanks to all these macros, one can build the trajectories of a
\emph{spirograph} point of the gear. However, \mpgears provides a dedicated
macro. 

\begin{colourband}
\commande|spirographCurve(«A»,«B»,«n»,«t»)|\return{\typeMP{path}}\smallskip\index{spirographCurve@\lstinline+spirographCurve+}
\begin{description}
  \item[\meta{A}:] \typeMP{numeric} identifier of the fixed gear.
  \item[\meta{B}:]  \typeMP{numeric} identifier of the rotating gear.
  \item[\meta{n}:] \typeMP{numeric}, integer between 0 and \lstinline+getSpirographPointNbr(+\meta{id}\lstinline+)+.  
  \item[\meta{t}:] \typeMP{numeric} angle of total rotation around \meta{A}.
\end{description}
\end{colourband}

Here, are two examples. Because one revolution is 360 degrees, if we use
the default number system of \hologo{METAPOST}, we are limited to very few
revolutions. 

\mplibnumbersystem{double}
\begin{ExempleMP}
input gears
% double number system
beginfig(1);
  N:=10;
  (Q,P) = buildExternalGearPair(27,10,0.5,20,(0,0),0,0);
  drawGear(Q,(0.7,0.3,0.3),"classical");
  drawGear(P,(0.3,0.7,0.3), "spirograph");
  draw spirographCurve(Q,P,N,3600) withcolor (0.3,0.3,0.7);
  drawdot getSpirographPoint(P,N) withpen pencircle scaled 4pt withcolor (0.9,0.6,0.3);
endfig;
\end{ExempleMP}

\begin{ExempleMP}
input gears
% double number system
beginfig(1);
  N:=10;
  (Q,P) = buildInternalGearPair(20,12,0.5,20,(0,0),0,0);
  drawGear(Q,(0.7,0.3,0.3),"classical");
  drawGear(P,(0.3,0.7,0.3), "spirograph");
  draw spirographCurve(Q,P,N,3600) withcolor (0.3,0.3,0.7);
  drawdot getSpirographPoint(P,N) withpen pencircle scaled 4pt withcolor (0.9,0.6,0.3);
endfig;
\end{ExempleMP}

You can get or modify the size of the mark of the spirograph point on the gear with the
following macros. In the \mpgears unit, the size is \num{0.15} by default.


\begin{colourband}
\commande|getSpirographPointSize|\return{\typeMP{numeric}}\smallskip\index{getSpirographPointSize@\lstinline+getSpirographPointSize+}
\end{colourband}


\begin{colourband}
\commande|setSpirographPointSize(«s»)|\smallskip\index{setSpirographPointSize@\lstinline+setSpirographPointSize+}
\begin{description}
\item[\meta{s}:] \typeMP{numeric} size of the spirograph points (\num{0.15} by default).
\end{description}
\end{colourband}

\subsection{Cycloid Curve}

Similar to \lstinline+spirographCurve+, it is possible to draw hypo or
epicycloids.


\begin{colourband}
\commande|cycloidCurve(«A»,«B»,«t»)|\return{\typeMP{path}}\smallskip\index{cycloidCurve@\lstinline+cycloidCurve+}
\begin{description}
  \item[\meta{A}:] \typeMP{numeric} identifier of the fixed gear.
  \item[\meta{B}:]  \typeMP{numeric} identifier of the rotating gear.
  \item[\meta{t}:] \typeMP{numeric} angle of total rotation around \meta{A}.
\end{description}
\end{colourband}

\begin{ExempleMP}
input gears
% double number system
beginfig(1);
  (Q,P) = buildInternalGearPair(20,12,0.5,20,(0,0),0,0);
  drawGear(Q,(0.7,0.3,0.3),"classical");
  drawGear(P,(0.3,0.7,0.3), "classical");
  draw cycloidCurve(Q,P,7200) withcolor (0.3,0.3,0.7);
  drawdot getRadialPoint(P,1) withpen pencircle scaled 4pt withcolor (0.9,0.6,0.3);
endfig;
\end{ExempleMP}



\section{History}

\begin{description}
  \item[2026-05-05:] Change of last parameter of \lstinline+spirographCurve+:
  number of revolution becomes total angle of rotation.  Bug correction in
  \lstinline+spirographCurve+. New: \lstinline+cycloidCurve+. New animations for
  cycloid and spirograph. 
\end{description}

\pagestyle{empty}
\begin{landscape}
  \section{Gallery}
  \subsection{Clock Gear Train}
  Inspired by the remarkable work of Tavmjong Bah on the website: \url{http:
//tavmjong.free.fr/INKSCAPE/DRAWINGS/clock.svg} and \package{pst-gears}.


    \begin{center}
      \begin{mplibcode}
input gears 
color couleur[];
couleur1 := (0.7,0.3,0.3);
couleur2 := (0.3,0.7,0.3);
couleur3 := (0.3,0.3,0.7);
couleur4 := (0.6,0.6,0.6);

picture aiguille;

setUnit(1cm);
m := 0.08;
alpha := 20;

aiguille := image(
    R := 60*m/2;
    fill (-0.05*R,-0.3*R)--(0.05*R,-0.3*R)--(0.03*R,R)--(0,1.1*R)--
    (-0.03*R,R)--cycle;
    fill fullcircle scaled (0.1*2*R);
) scaled getUnit;

beginfig(1);
    
    rot := 0; 
    (G1,G2) = buildExternalGearPair(8,60,m,alpha,(0,0),rot,180);
    G3 = buildCompoundGear(G2,8,m,alpha);
    G4 = buildExternalGearFor(G3,64,180);
    G5 = buildCompoundGear(G4,20,m,alpha);
    G6 = buildExternalGearFor(G5,60,220);
    G7 = buildCompoundGear(G6,16,m,alpha);
    G8 = buildExternalGearFor(G7,64,140);
    
    drawGear(G1,couleur1,"clockwork");
    drawGear(G2,couleur1,"clockwork");
    drawGear(G3,couleur2,"clockwork");
    drawGear(G4,couleur2,"clockwork");
    drawGear(G5,couleur3,"clockwork");
    drawGear(G6,couleur3,"clockwork");
    drawGear(G7,couleur4,"clockwork");
    drawGear(G8,couleur4,"clockwork");

    draw aiguille xscaled 0.8 rotated getRotation(G1) shifted getCenter(G1); 
    draw aiguille rotated getRotation(G5) shifted getCenter(G5); 
    draw aiguille yscaled 0.6 rotated getRotation(G8) shifted getCenter(G8); 
endfig;
end.
      \end{mplibcode}
    \end{center}
    \newpage

  \begin{multicols}{2}
    \begin{lstlisting}
    input gears 
color couleur[];
couleur1 := (0.7,0.3,0.3);
couleur2 := (0.3,0.7,0.3);
couleur3 := (0.3,0.3,0.7);
couleur4 := (0.6,0.6,0.6);

picture aiguille;
setUnit(1cm);
m := 0.08;
alpha := 20;

aiguille := image(
    R := 60*m/2;
    fill (-0.05*R,-0.3*R)--(0.05*R,-0.3*R)--(0.03*R,R)--(0,1.1*R)--
    (-0.03*R,R)--cycle;
    fill fullcircle scaled (0.1*2*R);
) scaled getUnit;

beginfig(1);
    
    rot := 0; 
    (G1,G2) = buildExternalGearPair(8,60,m,alpha,(0,0),rot,180);
    G3 = buildCompoundGear(G2,8,m,alpha);
    G4 = buildExternalGearFor(G3,64,180);
    G5 = buildCompoundGear(G4,20,m,alpha);
    G6 = buildExternalGearFor(G5,60,220);
    G7 = buildCompoundGear(G6,16,m,alpha);
    G8 = buildExternalGearFor(G7,64,140);
    
    drawGear(G1,couleur1,"clockwork");
    drawGear(G2,couleur1,"clockwork");
    drawGear(G3,couleur2,"clockwork");
    drawGear(G4,couleur2,"clockwork");
    drawGear(G5,couleur3,"clockwork");
    drawGear(G6,couleur3,"clockwork");
    drawGear(G7,couleur4,"clockwork");
    drawGear(G8,couleur4,"clockwork");

    draw aiguille xscaled 0.8 rotated getRotation(G1) shifted getCenter(G1); 
    draw aiguille rotated getRotation(G5) shifted getCenter(G5); 
    draw aiguille yscaled 0.6 rotated getRotation(G8) shifted getCenter(G8); 
endfig;
end.
    \end{lstlisting}
  \end{multicols}
\end{landscape}
\begin{landscape}
\subsection{Gears Animation}

We can use the package \package{animate}~\cite{animate} to animate rotation of
gears. 

\begin{center}
\begin{animateinline}[poster=first,loop, controls]{12}%
\multiframe{360}{iAngle=0+2}{%
\begin{mplibcode}
input gears

beginfig(1);
    rot := \iAngle; 
    axerot := 30;
    axerot3 := -30;
    pair gears;
    gears := buildExternalGearPair(16,10,0.5,20,(0,0),rot,axerot);
    G1 := xpart gears;
    G2 := ypart gears; 
    G3 := buildExternalGearFor(G2,8,axerot3);
    
    drawGear(G1, (0.7,0.3,0.3),"classical");
    drawGear(G2, (0.3,0.7,0.3),"classical");
    drawGear(G3, (0.3,0.3,0.7),"classical");

    pair c[];
    c1 := getCenter(G1);
    c2 := getCenter(G2);
    c3 := getCenter(G3);
    draw (xpart c1-1.5*getTopRadius(G1),-1.5*getTopRadius(G1))--(xpart
    c3+1.5*getTopRadius(G3),-1.5*getTopRadius(G1))--(xpart
    c3+1.5*getTopRadius(G3),ypart c2+1.5*getTopRadius(G2))--(xpart
    c1-1.5*getTopRadius(G1),ypart c2+1.5*getTopRadius(G2)) --cycle withcolor background;
endfig;
\end{mplibcode}
}
\end{animateinline}
\end{center}
\begin{multicols}{2}
  \begin{lstlisting}
\begin{animateinline}[poster=first,loop, controls]{12}%
\multiframe{360}{iAngle=0+2}{%
\begin{mplibcode}
input gears

beginfig(1);
    rot := \iAngle; 
    axerot := 30;
    axerot3 := -30;
    pair gears;
    gears := buildExternalGearPair(16,10,0.5,20,(0,0),rot,axerot);
    G1 := xpart gears;
    G2 := ypart gears; 
    G3 := buildExternalGearFor(G2,8,axerot3);
    
    drawGear(G1, (0.7,0.3,0.3),"classical");
    drawGear(G2, (0.3,0.7,0.3),"classical");
    drawGear(G3, (0.3,0.3,0.7),"classical");
    
endfig;
\end{mplibcode}
}
\end{animateinline}
  \end{lstlisting}
\end{multicols}
\end{landscape}

\begin{landscape}
\subsection{Gears Animation (2)}

\begin{center}
\begin{animateinline}[poster=first, controls]{12}%
\multiframe{360}{iAngle=0+2}{%
\begin{mplibcode}
input gears

beginfig(2);
    rot := \iAngle; 
    axerot := 0;
    (G[7],G[8]) = buildInternalGearPair(60,24,0.2,20,(0,0),rot,axerot);
    G9 = buildExternalGearFor(G7,24,120);
    G10 = buildExternalGearFor(G7,24,240);
    G11 = buildExternalGearFor(G10,12,60);
    drawGear(G7,(0.7,0.3,0.3),"classical");
    drawGear(G8,(0.3,0.7,0.3),"classical");
    drawGear(G9,(0.3,0.7,0.3),"classical");
    drawGear(G10,(0.3,0.7,0.3),"classical");
    drawGear(G11,(0.3,0.3,0.7),"classical");
endfig;
\end{mplibcode}
}
\end{animateinline}
\end{center}
\begin{multicols}{2}
  \begin{lstlisting}
\begin{animateinline}[poster=first, controls]{12}%
\multiframe{360}{iAngle=0+2}{%
\begin{mplibcode}
input gears

beginfig(2);
    rot := \iAngle; 
    axerot := 0;
    (G[7],G[8]) = buildInternalGearPair(60,24,0.2,20,(0,0),rot,axerot);
    G9 = buildExternalGearFor(G7,24,120);
    G10 = buildExternalGearFor(G7,24,240);
    G11 = buildExternalGearFor(G10,12,60);
    drawGear(G7,(0.7,0.3,0.3),"classical");
    drawGear(G8,(0.3,0.7,0.3),"classical");
    drawGear(G9,(0.3,0.7,0.3),"classical");
    drawGear(G10,(0.3,0.7,0.3),"classical");
    drawGear(G11,(0.3,0.3,0.7),"classical");
endfig;
\end{mplibcode}
}
\end{animateinline}
  \end{lstlisting}
\end{multicols}
\end{landscape}

\begin{landscape}
\subsection{Epicycloid Animation}

\begin{center}
\begin{animateinline}[poster=first, controls]{12}%
\multiframe{217}{iAngle=0+5}{%
\begin{mplibcode}
input gears
% double number system
setUnit(0.3cm);
(Q,P) = buildExternalGearPair(20,12,0.5,20,(0,0),0,0);
path bb;
bb := bbox image(draw cycloidCurve(Q,P,1800);) scaled 1.3; 
beginfig(1);
  (R,S) = buildExternalGearPair(20,12,0.5,20,(0,0),0,\iAngle);
  drawGear(R,(0.7,0.3,0.3),"classical");
  drawGear(S,(0.3,0.7,0.3), "classical");
  draw cycloidCurve(Q,P,\iAngle) withcolor (0.3,0.3,0.7) withpen pencircle scaled 2pt;
drawdot getRadialPoint(S,1) withpen pencircle scaled 4pt withcolor
(0.9,0.6,0.3);
  draw bb withcolor background;
endfig;
\end{mplibcode}
}
\end{animateinline}

\end{center}
\begin{multicols}{2}
  \begin{lstlisting}
\begin{animateinline}[poster=first, controls]{12}%
\multiframe{217}{iAngle=0+5}{%
\begin{mplibcode}
input gears
% double number system
setUnit(0.3cm);
(Q,P) = buildExternalGearPair(20,12,0.5,20,(0,0),0,0);
path bb;
bb := bbox image(draw cycloidCurve(Q,P,1800);) scaled 1.3; 
beginfig(1);
  (R,S) = buildExternalGearPair(20,12,0.5,20,(0,0),0,\iAngle);
  drawGear(R,(0.7,0.3,0.3),"classical");
  drawGear(S,(0.3,0.7,0.3), "classical");
  draw cycloidCurve(Q,P,\iAngle) withcolor (0.3,0.3,0.7) withpen pencircle scaled 2pt;
drawdot getRadialPoint(S,1) withpen pencircle scaled 4pt withcolor
(0.9,0.6,0.3);
  draw bb withcolor background;
endfig;
\end{mplibcode}
}
\end{animateinline}
  \end{lstlisting}
\end{multicols}
\end{landscape}

\begin{landscape}
\subsection{Spirograph Animation}

\begin{center}
\begin{animateinline}[poster=first, controls]{12}%
\multiframe{217}{iAngle=0+5}{%
\begin{mplibcode}
input gears
% double number system
(Q,P) = buildInternalGearPair(20,12,0.5,20,(0,0),0,0);
N:=15;%getSpirographPointNbr(P);
beginfig(1);
  (R,S) = buildInternalGearPair(20,12,0.5,20,(0,0),0,\iAngle);
  drawGear(R,(0.7,0.3,0.3),"classical");
  drawGear(S,(0.3,0.7,0.3), "spirograph");
  draw spirographCurve(Q,P,N,\iAngle) withcolor (0.3,0.3,0.7) withpen pencircle scaled 2pt;
  drawdot getSpirographPoint(S,N) withpen pencircle scaled 4pt withcolor (0.9,0.6,0.3);
endfig;
\end{mplibcode}
}
\end{animateinline}

\end{center}
\begin{multicols}{2}
  \begin{lstlisting}
\begin{animateinline}[poster=first, controls]{12}%
\multiframe{217}{iAngle=0+5}{%
\begin{mplibcode}
input gears
% double number system
(Q,P) = buildInternalGearPair(20,12,0.5,20,(0,0),0,0);
N:=15;%getSpirographPointNbr(P);
beginfig(1);
  (R,S) = buildInternalGearPair(20,12,0.5,20,(0,0),0,\iAngle);
  drawGear(R,(0.7,0.3,0.3),"classical");
  drawGear(S,(0.3,0.7,0.3), "spirograph");
  draw spirographCurve(Q,P,N,\iAngle) withcolor (0.3,0.3,0.7) withpen pencircle scaled 2pt;
  drawdot getSpirographPoint(S,N) withpen pencircle scaled 4pt withcolor (0.9,0.6,0.3);
endfig;
\end{mplibcode}
}
\end{animateinline}
  \end{lstlisting}
\end{multicols}
\end{landscape}

\printbibliography
\printindex
\end{document}
