Draw a Frost circle in Latex
Honestly, it's taken some effort, but your figure was intriguing and it allowed me to learn new things1 so, it's all good.
Basically I've created a \newcommand
, name \Frostcircle
, which has 2 arguments, options and the electrons.
Currently, the [options]
are:
radius
= the radius of the circle, please note that at the moment the surrounding graphics do not adjust if you make it too big. I might work on it in the future. It only takes a number (incm
) at the moment, using lengths breaks it, I'm not sure why yet. Suggestions are welcome.ring size
= this refers to the number of sides of the polygon. Number of sides from 5 to 10 have been tested. As you might expect, it takes a number as argumentfrost label
= this is the label at the top, default is empty. Make sure to surround the text with curly braces, e.g.frost label={My label here}
The other argument are the electrons, the easiest way I could find is to set them in a counterclockwise fashion, starting from the top, as in this figure:
It takes values 0
, 1
, and 2
: in order, no electron, one electron, two electrons. You can supply it as a list so giving {0,0,2,2,2,0}
would give your benzene
frost circle. It might sound counterintuitive but it's actually simple once you give it a try.
If the number of elements in the list you provide are less than the ring size, you will get an error and the code will not compile. If you want no electron, just type 0
to solve this.
Notes
The direction of the "arrow" for the electron is inverted on the other side, not sure if this is important for your graphs. I can look into it another day if it's important. FIXED
Also I added the same packages as in Sebastiano's answer to get the math font, but they are not needed for the command to work.
Output
Code
\documentclass[margin=10pt]{article}
\usepackage{tikz}
\usepackage{newtxtext}
\usepackage{amssymb}
\usepackage{bm}
\usetikzlibrary{arrows.meta,decorations.markings,shapes.geometric}
\tikzset{%
electron/.style={%
postaction={decorate,
decoration={%
markings,
mark=at position .5 with
{%
\ifnum#1=1\relax%
\draw[-{Straight Barb[left,angle=60:2pt 3]}] (0,-6pt) --(0,6pt);
\else
\ifnum#1=2\relax%
\draw[-{Straight Barb[left,angle=60:2pt 3]}] (-1pt,-6pt) -- (-1pt,6pt);
\draw[{Straight Barb[left,angle=60:2pt 3]}-] (1pt,-6pt) -- (1pt,6pt);
\else
\fi\fi
}}
}
},
mlbl/.style={anchor=south, align=center, midway, sloped},
}
\pgfkeys{/tikz/.cd,% to set the path
radius/.initial=.8, % initial value
radius/.get=\circleradius, % to get the value from a macro
radius/.store in=\circleradius, % to store the value into a macro
ring size/.initial=5,
ring size/.get=\numbersides,
ring size/.store in=\numbersides,
frost label/.initial=,
frost label/.get=\frostlabel,
frost label/.store in=\frostlabel,
}
\newcommand\Frostcircle[2][]{%
\tikzset{radius=.8,ring size=5,frost label=,#1}
\begin{tikzpicture}[line width=1pt]
\draw[-{Stealth[scale=1.5]}] (0,0) -- (0,3cm)
node[mlbl] {Energy}
node[anchor=north west, xshift=2mm] {\frostlabel};
\draw[dotted, shorten >=-1cm] (.5,1) -- (4,1)
node[anchor=south west] {antibonding}
node[anchor=north west] {bonding};
\draw (2,1) circle (\circleradius);
\node[%
regular polygon,
rotate=360/\numbersides/2,
regular polygon sides=\numbersides,
minimum size=\circleradius*2 cm,
draw,
outer sep=0pt
] at (2,1) (FrostCircle) {};
\def\electronarrow{{#2}}
\foreach \polycorner [count=\findex starting from 0] in {1,...,\numbersides}{%
\pgfmathtruncatemacro\maximumhalf{\numbersides/2+1}
\pgfmathsetmacro\Findex{\electronarrow[\findex]}
\ifnum\polycorner=1\relax%
\draw[electron=\Findex] (FrostCircle.corner \polycorner)++(-.8,0) --++ (1.6,0);
\else
\ifnum\polycorner=\maximumhalf\relax%
\draw[electron=\Findex] (FrostCircle.corner \polycorner)++(-.8,0) --++ (1.6,0);
\else
\ifnum\polycorner<\maximumhalf\relax%
\draw[electron=\Findex] (FrostCircle.corner \polycorner)++ (-.8,0) -- (FrostCircle.corner \polycorner);
\else
\draw[electron=\Findex] (FrostCircle.corner \polycorner) --++ (.8,0);
\fi\fi\fi
}%
\end{tikzpicture}%
}
\begin{document}
\Frostcircle[%
ring size=6,
radius=1,
frost label={benzene (ring size = 6, electrons = 6)}
]{0,0,2,2,2,0}
\vspace{1cm}
\Frostcircle[%
ring size=5,
radius=1,
frost label={cyclopentadienyl cation (ring size = 5, electrons = 4)}
]{0,1,2,1,0}
\vspace{1cm}
\Frostcircle[%
ring size=8,
radius=1,
frost label={cyclooctatetraene (ring size = 8, electrons = 8)}
]{0,0,1,2,2,2,1,0}
\end{document}
1: The pgfkeys
.
Here is a fully automated solution. The calls for your three examples are
\frost{6}{6}
\frost{5}{4}
\frost{8}{8}
There is an optional argument for radius size. Default is 1cm. So frost[2cm]{6}{6}
would have a radius of 2cm.
Note: This only works (at the moment) if there are an even number of electrons.
\documentclass{article}
\usepackage{tikz}
\usepackage{ifthen}
\usetikzlibrary{decorations.markings}
\tikzset% Define decorations
{updown/.style={postaction=decorate, decoration={markings, mark=at position .5 with
{\draw[line join=round] (-2pt,-\arrlen)--++(0pt,2*\arrlen)--(-4pt,1pt);
\draw[line join=round] (2pt,\arrlen)--++(0pt,-2*\arrlen)--(4pt,-1pt);
}}},% 2 arrows
uparr/.style={postaction=decorate, decoration={markings, mark=at position .5 with
{\draw[line join=round] (0pt,-\arrlen)--++(0pt,2*\arrlen)--(-2pt,1pt);
}}},% 1 arrow, right side
dnarr/.style={postaction=decorate, decoration={markings, mark=at position .5 with
{\draw[line join=round] (0pt,\arrlen)--++(0pt,-2*\arrlen)--(2pt,-1pt);
}}}% 1 arrow left side (points down since lines will be drawn right to left)
}
\newcommand{\orblen}{.8}% length of horizontal segments as a percentage of main radius
\newcommand{\arrlen}{.25cm}% half length of each arrow
\newcommand{\frost}[3][1cm]% optional argument is circle radius, #2=edges, #3=electrons
{\begin{tikzpicture}[line width=1pt]
\draw(0,0)circle[radius=#1];% main circle
\ifthenelse{#3 = 0}{\draw(-.5*#1*\orblen,-#1)--(.5*#1*\orblen,-#1);}% draw bottom line segment...
{\draw[updown](-.5*#1*\orblen,-#1)--(.5*#1*\orblen,-#1);}% ...with arrows if >0 electrons
\foreach \k [evaluate=\k as \r using .5*#2+1,% point right if k<r, point left if k>r, top if k=r
evaluate=\k as \t using (\k-1)*360/#2-90,% angles of polygon vertices. k=1 is bottom.
evaluate=\k as \n using -4*\k+6+#3,% who gets 2 electrons (right)?
evaluate=\k as \m using -4*(#2+2-\k)+6+#3,% who gets 2 electrons (left)?
evaluate=\k as \j using 2*#2] in {1,...,#2}% electrons for top if #3=2*#2
{\draw(\t:#1)--(\t+360/#2:#1);
\ifthenelse{\k>1}% already did bottom line.
{\ifthenelse{\lengthtest{\k pt < \r pt}}% right side
{\ifthenelse{3 < \n}{\draw[updown](\t:#1)--+(#1*\orblen,0);}% 2 arrows
{\ifthenelse{1 < \n}{\draw[uparr](\t:#1)--+(#1*\orblen,0);}% 1 arrow
{\draw(\t:#1)--+(#1*\orblen,0);}}}% no arrows
{\ifthenelse{\lengthtest{\k pt > \r pt}}% left side
{\ifthenelse{3 < \m}{\draw[updown](\t:#1)--+(-#1*\orblen,0);}% 2arrows
{\ifthenelse{1 < \m}{\draw[dnarr](\t:#1)--+(-#1*\orblen,0);}% 1 arrow
{\draw(\t:#1)--+(-#1*\orblen,0);}}}%no arrows
{\ifthenelse{#3 = \j}{\draw[updown](-.5*#1*\orblen,#1)--(.5*#1*\orblen,#1);}% 2 arrows on top
{\draw(-.5*#1*\orblen,#1)--(.5*#1*\orblen,#1);}}} % no arrows on top
}{} % do nothing if k=1 (bottom)
}
\draw[dotted](-2*#1,0)--(3*#1,0)node[below]{bonding\phantom{anti}}node[above]{antibonding};
\draw[-latex](-2.2*#1,-#1)--node[sloped,above,pos=.4]{Energy}(-2.2*#1,1.8*#1);
\end{tikzpicture}
}
\begin{document}
\frost{6}{6}
\frost{5}{4}
\frost{8}{8}
\end{document}
I have done with Mathcha the first example. For my humble opinion it seem very similar...but there is a latin maxime: "de gustibus non disputandum est".
\documentclass[a4paper,12pt]{article}
\usepackage{tikz}
\usepackage{newtxtext}
\usepackage{amssymb}
\usepackage{bm}
\begin{document}
\tikzset{every picture/.style={line width=0.75pt}} %set default line width to 0.75pt
\begin{tikzpicture}[x=0.75pt,y=0.75pt,yscale=-1,xscale=1]
%uncomment if require: \path (0,300); %set diagram left start at 0, and has height of 300
%Shape: Regular Polygon [id:dp9024119328579219]
\draw [line width=1.5] (203,184) -- (161.86,160.25) -- (161.86,112.75) -- (203,89) -- (244.14,112.75) -- (244.14,160.25) -- cycle ;
%Shape: Circle [id:dp3742321630799761]
\draw [line width=1.5] (155.5,136.5) .. controls (155.5,110.27) and (176.77,89) .. (203,89) .. controls (229.23,89) and (250.5,110.27) .. (250.5,136.5) .. controls (250.5,162.73) and (229.23,184) .. (203,184) .. controls (176.77,184) and (155.5,162.73) .. (155.5,136.5) -- cycle ;
%Straight Lines [id:da6431705906977057]
\draw [line width=1.5] (101,185) -- (101,31.71) ;
\draw [shift={(101,27.71)}, rotate = 450] [fill={rgb, 255:red, 0; green, 0; blue, 0 } ][line width=0.08] [draw opacity=0] (13.4,-6.43) -- (0,0) -- (13.4,6.44) -- (8.9,0) -- cycle ;
%Straight Lines [id:da03628267423150655]
\draw [line width=1.5] (176.75,89) -- (229.25,89) ;
%Straight Lines [id:da6999074691962319]
\draw [line width=1.5] (244.14,112.75) -- (285.5,112.75) ;
%Straight Lines [id:da6267867712352968]
\draw [line width=1.5] (120.5,112.75) -- (161.86,112.75) ;
%Straight Lines [id:da4603867099439829]
\draw [line width=1.5] (244.14,160.25) -- (285.5,160.25) ;
%Straight Lines [id:da018369347304083128]
\draw [line width=1.5] (120.5,160.25) -- (161.86,160.25) ;
%Straight Lines [id:da7545009709936943]
\draw [line width=1.5] (176.75,184) -- (229.25,184) ;
%Straight Lines [id:da42526907269791137]
\draw [line width=1.5] [dash pattern={on 1.69pt off 2.76pt}] (120.5,136.5) -- (346.5,136.5) ;
% Text Node
\draw (126,149.4) node [anchor=north west][inner sep=0.75pt] [font=\large] {$\bm{\upharpoonleft }$};
% Text Node
\draw (249,149.4) node [anchor=north west][inner sep=0.75pt] [font=\large] {$\bm{\upharpoonleft }$};
% Text Node
\draw (195,173.4) node [anchor=north west][inner sep=0.75pt] [font=\large] {$\bm{\upharpoonleft }$};
% Text Node
\draw (130,149.4) node [anchor=north west][inner sep=0.75pt] [font=\large] {$\bm{\downharpoonright }$};
% Text Node
\draw (253,149.4) node [anchor=north west][inner sep=0.75pt] [font=\large] {$\bm{\downharpoonright }$};
% Text Node
\draw (200,173.4) node [anchor=north west][inner sep=0.75pt] [font=\large] {$\bm{\downharpoonright }$};
% Text Node
\draw (74,149) node [anchor=north west][inner sep=0.75pt] [font=\large,rotate=-270] [align=left] {Energy};
% Text Node
\draw (288,103) node [anchor=north west][inner sep=0.75pt] [font=\large] [align=left] {Antibonding};
% Text Node
\draw (288,150) node [anchor=north west][inner sep=0.75pt] [font=\large] [align=left] {Bonding};
% Text Node
\draw (120,36) node [anchor=north west][inner sep=0.75pt] [align=left] {\large benzene (6 atoms, 6 electrons)};
\end{tikzpicture}
\end{document}