How can I create a Caesar's encryption disk with LaTeX?
I guess, the ultimate solution would take a arbitrary list of letters and calculate the spaces and angles for each letter automatically. So if I pass 4 letters to it, each space should have 90 degrees.
\drawCaesarsDisk
that works with a number of letters (only A to Z)\drawCaesarsList
that works with one list for both rings or two different listsinner radius
/middle radius
/outer radius
inner height
and outer height
respectively to calculate the actual radii.number of letters
(only \drawCaesarsDisk
)inner letters
and outer letters
(only \drawCaesarsList
): If only inner letters
is specified the letters in the outer ring will be the same as in the inner ring.shift
Bug: The List command breaks with
! Dimension too large. <recently read> \pgfmath@x
when 46 or more letters are specified.
I forgot something …
\documentclass[tikz]{standalone}
\usetikzlibrary{backgrounds}
\makeatletter
\tikzset{
/caesar/.cd,
inner radius/.store in=\qrr@caesar@innerR,
middle radius/.store in=\qrr@caesar@middleR,
outer radius/.store in=\qrr@caesar@outerR,
inner letters/.store in=\qrr@caesar@innerL,
outer letters/.store in=\qrr@caesar@outerL,
number of letters/.code=\pgfmathtruncatemacro\qrr@caesar@number{#1},
shift/.store in=\qrr@caesar@shift,
% defaults:
outer letters=,
shift=0
}
\newcommand*{\drawCaesarsDisk}[2][]{%
\begingroup
\pgfqkeys{/caesar}{#1}%
\foreach \radius in {\qrr@caesar@innerR,\qrr@caesar@middleR,\qrr@caesar@outerR}
\draw (#2) circle [radius=\radius];
\foreach \step in {0,...,\numexpr\qrr@caesar@number-1}{
\draw[shift={(#2)}] (\step*360/\qrr@caesar@number:\qrr@caesar@innerR) -- (\step*360/\qrr@caesar@number:\qrr@caesar@outerR);
\node[shift={(#2)},rotate=(\step+.5)*360/\qrr@caesar@number-90] at ({(\step+.5)*360/\qrr@caesar@number}:{.5*(\qrr@caesar@innerR)+.5*(\qrr@caesar@middleR)} ) {\@Alph{\numexpr26-\step}};
\pgfmathtruncatemacro\pgf@temp{mod(\step+\qrr@caesar@shift,\qrr@caesar@number)}%
\node[shift={(#2)},rotate=(\step+.5)*360/\qrr@caesar@number-90] at ({(\step+.5)*360/\qrr@caesar@number}:{.5*(\qrr@caesar@outerR)+.5*(\qrr@caesar@middleR)} ) {\@Alph{\numexpr26-\pgf@temp}};
}
\endgroup
}
\newcount\qrr@caesar@c
\newcommand*{\drawCaesarsList}[2][]{%
\begingroup
\pgfqkeys{/caesar}{#1}%
\foreach \radius in {\qrr@caesar@innerR,\qrr@caesar@middleR,\qrr@caesar@outerR}
\draw (#2) circle [radius=\radius];
\qrr@caesar@c=0\relax
\foreach \element in \qrr@caesar@innerL {\global\advance\qrr@caesar@c1}
\ifx\pgfutil@empty\qrr@caesar@outerL
\let\qrr@caesar@outerL\qrr@caesar@innerL
\fi
\edef\qrr@caesar@number{\number\qrr@caesar@c}%
\foreach \innerLetter[count=\step from 0] in \qrr@caesar@innerL {
\draw[shift={(#2)}] (\step*360/\qrr@caesar@number:\qrr@caesar@innerR) -- (\step*360/\qrr@caesar@number:\qrr@caesar@outerR);
\node[shift={(#2)},rotate=-(\step+.5)*360/\qrr@caesar@number-90] at ({-(\step+.5)*360/\qrr@caesar@number}:{.5*(\qrr@caesar@innerR)+.5*(\qrr@caesar@middleR)} ) {\innerLetter};
}
\foreach \outerLetter[count=\step@ from 0] in \qrr@caesar@outerL {
\ifnum\step@=\qrr@caesar@number\breakforeach\fi
\pgfmathtruncatemacro\step{mod(\step@+\qrr@caesar@shift,\qrr@caesar@number)}%
\node[shift={(#2)},rotate=-(\step+.5)*360/\qrr@caesar@number-90] at ({-(\step+.5)*360/\qrr@caesar@number}:{.5*(\qrr@caesar@outerR)+.5*(\qrr@caesar@middleR)} ) {\outerLetter};
}
\endgroup
}
\makeatother
\begin{document}
\begin{tikzpicture}
\drawCaesarsDisk[
inner radius=2cm,
middle radius=2cm+1.3em,
outer radius=2cm+3em,
number of letters=26,
shift=13,
]{0,0}
\end{tikzpicture}
\begin{tikzpicture}
\drawCaesarsList[
inner radius=.5cm,
middle radius=.5cm+1.3em,
outer radius=.5cm+3em,
inner letters={a,b,c,d,e,f,g},
outer letters={A,B,C,D,E,F,G}
]{2,0}
\end{tikzpicture}
\begin{tikzpicture}
\drawCaesarsList[
inner radius=2cm,
middle radius=2cm+1.3em,
outer radius=2cm+3em,
inner letters={a,...,z,A,B,...,T},%,U,V,W,X,Y,Z},
shift=26,
]{0,0}
\end{tikzpicture}
\end{document}
shift
. - Qrrbrbirlbel
\foreach
list is: \foreach \x [count=\c from 1, remember=\c] in {A,...,Z}{}
. Then \c
holds the length of the list. - Mark Wibrow
Here is what I've done so far:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\pgfmathsetmacro{\alphsize}{26}
\pgfmathsetmacro{\ang}{360/\alphsize}
\pgfmathsetmacro{\d}{10}
\pgfmathsetmacro{\op}{98 + \ang/2 - 1.2}
\pgfmathsetmacro{\e}{\ang + \ang*\d}
\pgfmathsetmacro{\ep}{\op + \ang*\d}
\foreach \x in {0,\ang,...,360} {
\draw[gray] (\x:8em) -- (\x:12em);
}
\foreach \x [count=\xi] in {A,...,Z} {
\node[rotate=\ang - \ang*\xi] at (\op - \ang*\xi:11em) {\Large\x};
\node[rotate=\e - \ang*\xi] at (\ep - \ang*\xi:9em) {\Large\x};
}
\draw[thick] (0cm,0cm) circle(12em);
\draw[gray] (0cm,0cm) circle(10em);
\draw[thick] (0cm,0cm) circle(8em);
\end{tikzpicture}
\end{document}
Here:
\documentclass{article}
\usepackage{tikz}
\usepackage{ifthen}
\newcounter{encrypted}
\newcounter{original}
\newcommand{\increase}[1]{%command to increase a counter by 1 modulo 26
\ifthenelse{\arabic{#1}<26}{\addtocounter{#1}{1}}{\setcounter{#1}{1}}
}
\begin{document}
\setcounter{encrypted}{7}
\setcounter{original}{1}
\begin{tikzpicture}[scale=0.5]
\draw(0,0)circle(5)circle(7)circle(9);
\foreach \x in {1,2,...,26}
{
\draw(\x*360/26:5)--(\x*360/26:9);
\node at (\x*360/26+360/26+180/26:6){\Alph{encrypted}};
\node at (\x*360/26+360/26+180/26:8){\Alph{original}};
\increase{encrypted}
\increase{original}
}
\end{tikzpicture}
\end{document}
:-)
- hpesoj626
Just 4 fun with PSTricks.
\documentclass[pstricks,border=12pt]{standalone}
\SpecialCoor
\makeatletter
\def\N{26}
\begin{document}
% speficy the angular distance between the 2 sets of alphabets
\def\offset{13}
\begin{pspicture}(-5,-5)(5,5)
\psforeach{\r} {2,3,4}{\pscircle{\r}}
\degrees[\N]
\psforeach{\t}{65,66,..,90}{%
\psline(2;\the\psLoopIndex)(4;\the\psLoopIndex)
\pstVerb{/angle {\the\psLoopIndex\space 0.5 add} bind def}%
\rput{!angle 6.5 sub}(!3.5 angle \pst@angleunit PtoC){\char\t\relax}
\rput{!angle \offset\space add 6.5 sub}(!2.5 angle \offset\space add \pst@angleunit PtoC){\char\t\relax}
}
\end{pspicture}
\end{document}
To be funner!
\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\SpecialCoor
\makeatletter
\def\N{26}
\begin{document}
\multido{\i=0+1}{\N}{%
% speficy the angular distance between the 2 sets of alphabets
\def\offset{\i}
\begin{pspicture}(-5,-5)(5,5)
\psforeach{\r} {2,3,4}{\pscircle{\r}}
\degrees[\N]
\psforeach{\t}{65,66,..,90}{%
\psline(2;\the\psLoopIndex)(4;\the\psLoopIndex)
\pstVerb{/angle {\the\psLoopIndex\space 0.5 add} bind def}%
\rput{!angle 6.5 sub}(!3.5 angle \pst@angleunit PtoC){\char\t\relax}
\rput{!angle \offset\space add 6.5 sub}(!2.5 angle \offset\space add \pst@angleunit PtoC){\char\t\relax}
}
\end{pspicture}}
\end{document}
If we invoke \degrees[<value other than 360>]
previously, conversion with \pst@angleunit
is needed for representing points in RPN notation but it is NOT need for representing rotation angle. See the following code snippet.
\rput{!angle 6.5 sub}(!3.5 angle \pst@angleunit PtoC){\t}
It is funny? Don't ask me! I just knew this feature several minutes ago!
One more feature, unlike \foreach \t in {A,...,Z}{}
that produces a correct result, \psforeach{\t}{A,..,Z}{}
produces a weird output!
The answer below uses the wheelchart [1] package, which I wrote.
The letters are placed in the diagram with the key wheel data
. Their position is determined by the key wheel data pos
. The letters are rotated using the key wheel data style
.
\documentclass[border=6pt]{standalone}
\usepackage{wheelchart}
\begin{document}
\begin{tikzpicture}
\makeatletter
\pgfkeys{
/wheelchart,
slices style={draw,fill=none},
total count=26,
wheel data=\@Alph{\WCcount},
wheel data pos=0.5,
wheel data style={rotate=\WCmidangle-90}
}
\makeatother
\wheelchart[
start angle=90+4*(360/26)
]{}
\wheelchart[
radius={3}{4},
start angle=90+1*(360/26)
]{}
\end{tikzpicture}
\end{document}
Below, a command \caesar
is defined. The first argument is optional and can contain keys for the inner ring. The second argument is mandatory and contains the letters for the inner ring. The third and fourth argument are similar for the outer ring.
\documentclass[border=6pt]{standalone}
\usepackage{wheelchart}
\NewDocumentCommand\caesar{O{}mO{}m}
{
{%note the double braces {{...}} so that the contents is in a group and in particular, \pgfkeys is applied locally
\pgfkeys{
/wheelchart,
data=,
slices style={draw,fill=none},
value=1,
wheel data=\WCvarA,
wheel data pos=0.5,
wheel data style={rotate=\WCmidangle-90}
}
\wheelchart[#1]{#2}
\wheelchart[#3]{#4}
}
}
\begin{document}
\begin{tikzpicture}
\caesar[radius={1}{2},slices style={draw=black,fill=gray!20},start angle=90+5*(360/7)]{e,n,c,r,y,p,t}[slices style={draw=black,fill=gray!50},start angle=90+2*(360/7)]{E,N,C,R,Y,P,T}
\end{tikzpicture}
\end{document}
[1] https://ctan.org/pkg/wheelchartJust for fun, with OpTeX. Note, we needn't use TikZ.
\fontfam[lm]
\newdimen\radiusA \radiusA=50pt % radius od big circle
\newdimen\radiusB \radiusB=35pt % radius of medium circle
\newdimen\radiusC \radiusC=24pt % radius of inner circle
\newdimen\radiusD \radiusD=\dimexpr\radiusA-\radiusB
\def\letterlist{ABCDEFGHIJKLMNOP} % list of used characters
\def\getletter{\ifx\letterlist\empty \def\useletter{}\else \ea\getletterA\letterlist\end \fi}
\def\getletterA#1#2\end{\def\useletter{#1}\def\letterlist{#2}}
\def\rul{\vrule height.75\radiusD depth.25\radiusD}
\def\circ#1#2#3{{% #1: first angle, #2: number of items, #3: object
\pdfsave \pdfrotate{#1}%
\fornum 0..#2-1 \do {\ifx\useletter#3\getletter\fi
\pdfsave\pdfrotate{-##1*360/#2}%
\raise\dimexpr\tmpdim+.25\radiusD \hbox to0pt{\hss#3\hss}\pdfrestore}%
\pdfrestore
}}
\def\cdisk#1#2{% #1: number of items, #2: shift in second disc
\hbox to2\radiusA{\hss
\incircle[\vvkern=\radiusA \hhkern=0pt]{}%
\incircle[\vvkern=\radiusB \hhkern=0pt]{}%
\incircle[\vvkern=\radiusC \hhkern=0pt]{}%
\sans\bf
\tmpdim=\radiusB \circ{0}{#1}\useletter \circ{180/#1}{#1}\rul
\typoscale[800/]\sans\bf \radiusD=\dimexpr \radiusB-\radiusC
\tmpdim=\radiusC \circ{-(#2*360)/#1}{#1}\useletter \circ{180/#1}{#1}\rul
\hss}}
\cdisk{15}{5} % prints a disk with 2x15 letters, second disc shifted by 5
\bye
TeX
? en.wikipedia.org/wiki/Enigma_machine - Ethan Bolker