# Flatten an arc while keeping length fixed

Question: How to ensure the blue shape of the second picture has same length as the annulus in the first picture?

Context: To illustrate the process of "un-coiling" the annulus after a straight cut. I plan to make an animation with 3 or 4 intermediate steps from "circle" to "line".

\documentclass[border=5mm, varwidth]{standalone}
\usepackage{tikz}
\begin{document}

\begin{tabular}{@{}c@{}}

\begin{tikzpicture}
\end{tikzpicture}

\vspace{2cm} \\

\begin{tikzpicture}
\filldraw[fill=blue!15, draw=black, shift={(0,2)}] (330:3) arc (330:210:3) -- (210:4) arc (210:330:4) -- cycle;
\end{tikzpicture}

\end{tabular}

\end{document}


Since the inner circle has radius 1cm and the outer circle radius 2cm, the length of the annulus would be about 3 times pi.

EDIT 1

I am hoping that something could be done with the nonlineartransformations PGF module. I have seen examples of transformations using polar coordinates and examples using arbitrary transformations. I think what I'm missing are the parametric equations that would flatten a semi-circle into a line. That is, if we forget about the thickness of the annulus and consider a semi-circle starting at (0,0) and ending at (0, 1) anti-clockwise, the transformation is one that would keep the point (0,0) unchanged but would pull (0,1) to the right and eventually down to the (1,0) point. Once I know how to produce the transformation to the rhs semi-circle, I can apply the symmetric transformation to the lhs semi-circle, to complete the circle transformation. And then do that for another pair of semi-circles with a different radius to get the annulus.

EDIT 2

With John Kormylo's suggestions (thanks John!), I was able to write a function that transforms the semi-circle to "flatten" it. Next is to generalize this to a \filldraw command for an annulus.

\documentclass[margin=3mm,varwidth]{standalone}
\usepackage{tikz}

\makeatletter
\pgfmathdeclarefunction{alpha}{1}{%
\begingroup
\pgfmathparse{180/#1-90}%
\pgf@x=\pgfmathresult pt\relax
\pgfmathreturn\pgf@x
\endgroup
}
\makeatother

\def\shape#1#2{
\draw [draw={#1}] (0,0) arc[start angle=-90, end angle={alpha(#2)}, radius={#2}];
}

\begin{document}

\begin{tikzpicture}[scale=3]
\shape{red}{1}
\shape{red!90}{2}
\shape{red!80}{3}
\shape{red!70}{4}
\shape{red!60}{5}
\shape{red!50}{6}
\shape{red!40}{7}
\shape{red!30}{8}
\shape{red!20}{9}
\shape{black}{100}
\end{tikzpicture}

\end{document}


The left-hand side follows by symmetry. Putting it together yields a somewhat unwieldy function with 6 arguments, including color, center, radius, and angles. This is still not an answer to my original question, so I'm including it here, rather than posting it as an answer. Also, I'm pretty sure the code can be cleaned up.

\documentclass[margin=3mm,varwidth]{standalone}
\usepackage{tikz}

% alpha takes 2 arguments:
% #1: angle of arc, for semi-circle either -180 or 180
% #3: rotation of angle
\makeatletter
\pgfmathdeclarefunction{alpha}{3}{%
\begingroup
\pgfmathparse{#1/#2+#3}%
\pgf@x=\pgfmathresult pt\relax
\pgfmathreturn\pgf@x
\endgroup
}
\makeatother

% \shape takes 5 arguments:
% #1: draw color, e.g. red
% #2: center, e.g. (0,0)
% #4: start angle, e.g. 0 for starting at (1,0), -90 for (0,-1)
% #5: angle of arc, for semi-circle either -180 or 180
% #6: rotation of end angle, e.g. -90 to go from (1,0) to (0,-1)
\def\shape#1#2#3#4#5#6{
\draw [draw={#1}] {#2} arc[radius={#3}, start angle={#4}, end angle={alpha(#6,#3,#5)}];
}

\begin{document}

\begin{tikzpicture}[scale=1.8]

\shape{blue!100}{(0,0)}{1}{-90}{-90}{180}
\shape{blue!100}{(0,0)}{1}{-90}{-90}{-180}

\shape{blue!80}{(0,0)}{2}{-90}{-90}{180}
\shape{blue!80}{(0,0)}{2}{-90}{-90}{-180}

\shape{blue!60}{(0,0)}{6}{-90}{-90}{180}
\shape{blue!60}{(0,0)}{6}{-90}{-90}{-180}

\shape{blue!50}{(0,0)}{150}{-90}{-90}{180}
\shape{blue!50}{(0,0)}{150}{-90}{-90}{-180}

\end{tikzpicture}

\end{document}


• Since arcs are drawn using angles, $\theta = \frac{2\pi r_0}{r}$ as the arc radius $r$ increases. You might want to use a thinner annulus in your diagram. Commented Jun 20, 2020 at 11:38
• @JohnKormylo, Thanks for your feedback. I have edited my question to simplify it. Basically right now I'm asking how to transform a semi-circle to a straight line by "pulling" from the top down, keeping one extremity fixed. Hope my objective is clear. Commented Jun 23, 2020 at 9:49
• 180^\circ at 1cm corresponds to 120^\circ at 1.5 cm and 72^\circ at 2.5cm, so your end angles should be 90, 30 and -18. Commented Jun 23, 2020 at 13:07
• Thanks John! I was able to do as you say for the semi-circle. Now if I find a bit of spare time later today, I'll try to do that for an annulus. Commented Jun 23, 2020 at 18:50
• As $r\to\infty$ you might use a straight line of length $2\pi r_0$. Pgfmath has a somewhat limited range of values. Commented Jun 24, 2020 at 15:39

1. flattening the annulus

2. flattening and stretching the annulus.

Assume that the annulus is a family of concentric circles spread between the interior and exterior frontier circles. Each circle of this family is transformed during the flattening process and eventually becomes a segment. In the first construction, the length of these curves is constant throughout the process. In particular, the region of the plane that represents the deformed annulus has constant area. In the second construction, these curves have increasing length, but the one corresponding to the exterior circle.

Before giving the code some explanations. We consider an annulus with S and N two diametrically opposed points on the exterior circle C. We denote by T_S the tangent line to C at S. We cut the annulus along the ray passing through N and want to flatten it such that, at the end, the curve corresponding to the exterior circle becomes a segment contained in the tangent line T_S with S its midpoint.

I'll briefly explain the first construction which appears, for example, in Cavalieri's work on the method of indivisibles; see https://fr.wikipedia.org/wiki/M%C3%A9thode_des_indivisibles#:~:text=spirale%20d'Archim%C3%A8de.-,Aire%20du%20disque,varie%20de%200%20%C3%A0%20R. It is based on the following idea: to flatten the exterior circle let's say, we imagine it as being a wire with its end points at N, wound around a disk which is tangent to T_S. If the disk's radius increases but the disk remains tangent to T_S, the evolution of the wire gives the desired flattening process of the circle.

The construction is build around this limiting process; there is a set of circles C_k with increasing radii that describe the flattening process of the exterior circle (see the figure above). The interior circle is forced to follow the exterior one in the sens that its flattening process is defined by circles that are concentric to the corresponding C_k circles and remain tangent to the fixed point S'.

To finish the construction, we compute the angles defining all these arcs for each value of k (done through the variable \q in the code bellow).

The code for the first construction

\documentclass[margin=10pt]{standalone}
\usepackage[rgb]{xcolor}
\usepackage{tikz}
\usetikzlibrary{math, calc}
\xdefinecolor{O}{RGB}{255, 102, 17}
\xdefinecolor{R}{RGB}{238, 34, 34}
\xdefinecolor{B}{RGB}{17, 87, 221}

\begin{document}
\tikzmath{%
real \r, \R, \h, \q;
\r = 1.5;
\R = 2.75;
\h = \R-\r;
}
\begin{tikzpicture}[every node/.style={scale=0.8}, rotate=-90]
\path[clip] (-\R-2, -10) rectangle (\R+1, 10);
\path
(\R, 0) coordinate (S)
(-\R, 0) coordinate (N);

\draw[B, fill=B!30, fill opacity=.5, even odd rule]
(0, 0) circle (\r)
(0, 0) circle (\R);

% \foreach \k [evaluate=\k as \q using \r/(\k*\R-\h)]
% in {1.03, 1.1, 1.2, 1.32, 1.5, 1.7, 2, 2.4, 3, 3.8, 5.1, 8, 17}{%
\foreach \k [evaluate=\k as \q using \r/(\k*\R-\h)]
in {1.03, 1.2, 1.5, 2, 3, 5, 8, 17}{%
\path
($({(1-\k)*\R}, 0) + (-{180*\q}: {\k*\R-\h})$) coordinate (A)
($({(1-\k)*\R}, 0) + ({180*\q}: {\k*\R-\h})$) coordinate (B)
($({(1-\k)*\R}, 0) + ({180/\k}: {\k*\R})$) coordinate (C)
($({(1-\k)*\R}, 0) + (-{180/\k}: {\k*\R})$) coordinate (D);
\draw[B, fill=B!30, fill opacity=.5]
(D) -- (A) arc ({-180*\q}: {180*\q}: {\k*\R-\h}) --
(B) -- (C) arc ({180/\k}: {-180/\k}: {\k*\R}) -- cycle;
}
\draw[B, fill=B!30, fill opacity=.5] (\r, -{3.142*\r}) -- (\r, {3.142*\r})
-- (\R, {3.142*\R}) -- (\R, -{3.142*\R}) -- cycle;
\end{tikzpicture}


In the code for the second construction, the lines corresponding to the \foreach command and the last two ones are replaced by what follows.

  \foreach \k in {1.03, 1.2, 1.5, 2, 3, 5, 8, 17}{%
\path
($({(1-\k)*\R}, 0) + (-{180/\k}: {\k*\R-\h})$) coordinate (A)
($({(1-\k)*\R}, 0) + ({180/\k}: {\k*\R-\h})$) coordinate (B)
($({(1-\k)*\R}, 0) + ({180/\k}: {\k*\R})$) coordinate (C)
($({(1-\k)*\R}, 0) + (-{180/\k}: {\k*\R})$) coordinate (D);
\draw[B, fill=B!30, fill opacity=.5]
(D) -- (A) arc ({-180/\k}: {180/\k}: {\k*\R-\h}) --
(B) -- (C) arc ({180/\k}: {-180/\k}: {\k*\R}) -- cycle;
}
\draw[B, fill=B!30, fill opacity=.5]
(\r, -{3.142*\R}) rectangle (\R, {3.142*\R});


Remark. Since the angles appearing in the command arc are angles measured with respect to the Ox axis (of the TikZ coordinate system), I made all the drawing vertically and then rotated the images.

With not too many changes, we can obtain animations of the two constructions.

Here is a code yielding the images that compose the first animation, for example.

\documentclass[multi=page, margin=10pt]{standalone}
\usepackage[rgb]{xcolor}
\usepackage{tikz}
\usetikzlibrary{math, calc}
\xdefinecolor{R}{RGB}{238, 34, 34}
\xdefinecolor{B}{RGB}{17, 87, 221}

\begin{document}
\tikzmath{%
real \r, \R, \h, \q;
\r = 1.5;
\R = 2.75;
\h = \R-\r;
}
\begin{page}
\begin{tikzpicture}[rotate=-90]
\path[clip] (-\R-2, -10) rectangle (\R+1, 10);
\draw[B, fill=B!50, even odd rule]
(0, 0) circle (\r)
(0, 0) circle (\R);
\end{tikzpicture}
\end{page}
\foreach \k [evaluate=\k as \q using \r/(\k*\R-\h)]
in {1.03, 1.1, 1.2, 1.32, 1.5, 1.7, 2, 2.4, 3, 3.8, 5.1, 8, 17}{%
\begin{page}
\begin{tikzpicture}[rotate=-90]
\path[clip] (-\R-2, -10) rectangle (\R+1, 10);
\path
($({(1-\k)*\R}, 0) + (-{180*\q}: {\k*\R-\h})$) coordinate (A)
($({(1-\k)*\R}, 0) + ({180*\q}: {\k*\R-\h})$) coordinate (B)
($({(1-\k)*\R}, 0) + ({180/\k}: {\k*\R})$) coordinate (C)
($({(1-\k)*\R}, 0) + (-{180/\k}: {\k*\R})$) coordinate (D);
\draw[B, fill=B!50]
(D) -- (A) arc ({-180*\q}: {180*\q}: {\k*\R-\h}) --
(B) -- (C) arc ({180/\k}: {-180/\k}: {\k*\R}) -- cycle;
\draw[R, thick] (A) -- (D)  (B) -- (C);
\end{tikzpicture}
\end{page}
}
\foreach \k in {1, 2, 3, 4}{% the last image lasts longer
\begin{page}
\begin{tikzpicture}[rotate=-90]
\path[clip] (-\R-2, -10) rectangle (\R+1, 10);
\draw[B, fill=B!50] (\r, -{3.142*\r}) -- (\r, {3.142*\r})
-- (\R, {3.142*\R}) -- (\R, -{3.142*\R}) -- cycle;
\draw[R, thick]
(\r, -{3.142*\r}) -- (\R, -{3.142*\R})
(\r, {3.142*\r}) -- (\R, {3.142*\R});
\end{tikzpicture}
\end{page}
}
\end{document}

• Speechless. This is amazing. Thanks! Commented Jul 25, 2020 at 9:03
• Thanks for the reference to the Cavalieri method. As it turns out my purpose in drawing this little animation was precisely the one detailed in the wikipedia page! Here is the note I was writing at the time (I haven't updated the figures yet, but will do): github.com/ptoche/Math/blob/master/ask-math-anything/… Commented Jul 25, 2020 at 9:22

This is a partial answer, but it feels appropriate to place my code here rather than editing my question over and over. Recap: my original question was (to coin a term) How to uncoil an annulus? My aim was to draw a "simulation" of cutting an annulus at the top and bending the two parts until they lay horizontally (see the first figure in my original question).

Part 1: Cutting and Bending an Arc

First, here is code that "uncoils arcs". The result is similar to what I presented in an edit to my question, except that now I have a more robust way of calculating the positions of the "fixed point" (in the example, the point in center-south position) and of the "cut point" (in the example, the point that starts at the center-north position and is gradually pulled to the left/right until it lies at a horizontal distance equal to the radius).

I modified the arc command to use the center of the circle as an input, rather than a point on the circumference (as intended with the arc command). Here is where I saw how to do that. I made one small change to the usual syntax because I wanted to be able to call this way: (center)(radius)(start angle:end angle). That's because I intend to call the annulus with: (center)(inner radius:outer radius)(start angle:end angle). I wanted to be able to input the center of the annulus, rather than a point on the circumference, because it seemed more natural to me.

I then introduced a dilation factor, that is the factor by which the radius of the arc is increased in order to give the uncoiling effect. The radius is increased from the "fixed point" to the center. To keep the length of the arc fixed, the "end angle" used in the arc command has to change according to the value of the dilation.

\documentclass[margin=3mm]{standalone}
\usepackage{tikz}
\usepackage[EULERGREEK]{sansmath}
\usetikzlibrary{calc}
\usetikzlibrary{shapes}
\usetikzlibrary{shapes.misc}% "cross out" shape
\usepackage{amssymb}% symbols
\pgfdeclarelayer{bg}
\pgfdeclarelayer{fg}
\pgfsetlayers{bg,main,fg}

\newcommand\arcus{}
\def\arcus(#1)(#2)(#3:#4){%
($(#1)+({#2*cos(#3)},{#2*sin(#3)})$)arc(#3:#4:#2)}

\newcommand\cutarcus{}
\def\cutarcus(#1)(#2)(#3:#4)(#5){%
($(#1)+({#2*cos(#3)},{#2*sin(#3)})$)arc(#3:#3+(#4-#3)/#5:#2*#5)}

% mark the cutpoint (depends on dilation factor)
\def\cutpoint[#1,(#2)](#3)(#4)(#5:#6)(#7){%
\path\cutarcus(#3)(#4)(#5:#6)(#7)node[#1,pos=1,font=\tiny]{#2};}

% mark the fixpoint (independent of dilation factor)
\def\fixpoint[#1,(#2)](#3)(#4)(#5:#6)(#7){%
\path\cutarcus(#3)(#4)(#5:#6)(#7)node[#1,pos=0,font=\tiny]{#2};}

\tikzset{%
center/.style={circle, fill, fill=white, draw=black, minimum size=2pt, inner sep=0pt, outer sep=0pt},
fixpoint/.style={diamond, fill, fill=black, draw=black, minimum size=2pt, inner sep=0pt, outer sep=0pt},
cutpoint/.style={circle, fill, fill=black, draw=black, minimum size=2pt, inner sep=0pt, outer sep=0pt},}

\begin{document}

\begin{tikzpicture}[font=\sffamily\tiny,scale=1]

% background layer
\begin{pgfonlayer}{bg}
% define grid lines
\draw[help lines, color=gray!30, dashed, line width=0.5pt]%
(-3.5,-1.5) grid (3.5,1.5);
\end{pgfonlayer}

% foreground layer
\clip (-1.5,-1.5) rectangle + (3,4.5);

\begin{pgfonlayer}{fg}

\foreach \m in {1,2,4,8,16,32,64}
%\foreach \m in {1,1.1,...,100}
{%
\draw[red]\cutarcus(0,0)(1)(270:90)(\m);
\draw[blue]\cutarcus(0,0)(1)(-90:90)(\m);
% label the cutpoints
\cutpoint[blue,($\bullet$)](0,0)(1)(-90:90)(\m);
\cutpoint[red,($\bullet$)](0,0)(1)(270:90)(\m);
}%

% label the center
\node at (0,0) [font=\tiny] {$\circ$};

% label the fixed point
\fixpoint[black,($\mathbin{\blacklozenge}$)](0,0)(1)(-90:90)(1);

% make a legend
\matrix [draw,below left] at (3,3) {
\node [center,label=right:center] {}; \\
\node [fixpoint,label=right:fixed point] {}; \\
\node [cutpoint,label=right:cut point] {}; \\
};

\end{pgfonlayer}

\end{tikzpicture}

\end{document}


The colors are just a way of indicating that I split the problem into two parts (here, left and right). If you look carefully at the code, you'll see that my legend was produced by creating tikz styles, while the labels in the figure rely on other code. That's because I produced the legend as an afterthought and I couldn't quickly see how to make the legend consistent with the symbols used (or vice versa), and decided to move on.

Part 2: Cutting and Bending an Annulus [UNFINISHED]

Now on to "cutting the annulus". The code appears to produce the correct lines, but sadly the color fill isn't applied properly. Perhaps someone can help me fix the problem. Or offer a better solution.

\documentclass[margin=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand\cutarcus{}
\def\cutarcus(#1)(#2)(#3:#4)(#5){%
($(#1)+({#2*cos(#3)},{#2*sin(#3)})$)arc(#3:#3+(#4-#3)/#5:#2*#5)}

\newcommand\cutannulus{}
\def\cutannulus[#1](#2)(#3:#4)(#5:#6)(#7){%
\filldraw[fill opacity=0.5,#1,even odd rule]\cutarcus(#2)(#3)(#5:#6)(#7)\cutarcus(#2)(#4)(#5:#6)(#7)}

\begin{document}

\begin{tikzpicture}

\filldraw[fill=gray!50]\arcus(0,0)(1)(-180:180);
\cutannulus[fill=blue!50](0,0)(1:2)(270:90)(1);
\cutannulus[fill=blue!50](0,0)(1:2)(-90:90)(1);

\begin{scope}[yshift=-5cm,on grid]
\filldraw[fill=gray!50]\arcus(0,0)(1)(-180:180);
\cutannulus[fill=blue!50](0,0)(1:2)(270:90)(1.5);
\cutannulus[fill=blue!50](0,0)(1:2)(-90:90)(1.5);
\end{scope}

\end{tikzpicture}

\end{document}


The fill color isn't applied properly:

Because of my limited experience in creating tikz commands, they are very sensitive to spaces. The arguments must be given without white spaces in between (and naturally, the bracket scheme must be respected).