Spiral spring in TikZ
You could use the plot
path (and polar coordinates):
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw [domain=0:25.1327,variable=\t,smooth,samples=75]
plot ({\t r}: {0.002*\t*\t});
\end{tikzpicture}
\end{document}
Note: to a full tikz-like command scroll to the bottom of the answer. (I'm sorry for the long text, I got excited)
A command implementation of Caramdir's answer with some definitions explanation.
The Goal: define a command \spiral
which makes a spiral from (coordinate)
of N
revolutions, has R
radius and ends in end angle
in the below syntax:
\spiral[options](placement)(end angle:N:R)
Using the plot
command with polar coordinates one can define a spiral as being a linear function (not necessary to be linear but makes things way easier) between radius and angle: r = f(θ) = B*θ
where the domain is the specified end angle plus the number of revolutions (domain=from 0 to "end angle"*180/pi + N*2*pi
- the 180/pi
is conversion from degrees to radians). Finally, to make it so that the spiral has radius R
the function parameter B
must be properly defined, since we want r(end of domain) = R
than R = B*"end of domain"
and therefore B=R/"end of domain"
. Implementing this to a new command:
\newcommand\spiral{}% Just for safety so \def won't overwrite something
\def\spiral[#1](#2)(#3:#4:#5){% \spiral[draw options](placement)(end angle:revolutions:final radius)
\pgfmathsetmacro{\domain}{pi*#3/180+#4*2*pi}
\draw [#1,
shift={(#2)},
domain=0:\domain,
variable=\t,
smooth,
samples=int(\domain/0.08)] plot ({\t r}: {#5*\t/\domain})
}
The shift key is used to place the spiral on the requested position, and the sampling is defined through the domain so the spiral will always be smooth (the meaning of \domain/0.08
is "take one point each 5 degrees (0.08 rad) of the domain
"). To get a ClockWise spiral just define the end radius
as a negative value and redefine the start angle
accordingly.
The whole code and an example:
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\newcommand\spiral{}% Just for safety so \def won't overwrite something
\def\spiral[#1](#2)(#3:#4:#5){% \spiral[draw options](placement)(end angle:revolutions:final radius)
\pgfmathsetmacro{\domain}{pi*#3/180+#4*2*pi}
\draw [#1,shift={(#2)}, domain=0:\domain,variable=\t,smooth,samples=int(\domain/0.08)] plot ({\t r}: {#5*\t/\domain})
}
\begin{document}
\begin{tikzpicture}
\spiral[red](0,0)(0:6:6);
\spiral[blue](0,0)(0:6:-6);
\spiral[blue](-12,0)(0:6:6);
\spiral[red](12,0)(0:6:-6);
\spiral[blue](-12,0)(90:2:-2.25);
\spiral[red](12,0)(90:2:2.25);
\end{tikzpicture}
\end{document}
Bonus spiral:
A bit more complete spiral definition would be to dictate start angle
, end angle
, start radius
, end radius
, number of revolutions
and placement
, right? I won't go about explaining the math, it's quite the same as before but the function is now something like r = f(θ) = A + B*(θ-θ_0)
and the domain is domain = "start angle":("end angle"+"revolutions")
. The syntax will now be:
\bonusspiral[options](placement)(start angle:end angle)(start radius:end radius)[revs]
And the command definition is:
\newcommand\bonusspiral{} % just for safety
\def\bonusspiral[#1](#2)(#3:#4)(#5:#6)[#7]{% \bonusspiral[draw options](placement)(start angle:end angle)(start radius:final radius)[revolutions]
\pgfmathsetmacro{\domain}{#4+#7*360}
\pgfmathsetmacro{\growth}{180*(#6-#5)/(pi*(\domain-#3))}
\draw [#1,
shift={(#2)},
domain=#3*pi/180:\domain*pi/180,
variable=\t,
smooth,
samples=int(\domain/5)] plot ({\t r}: {#5+\growth*\t-\growth*#3*pi/180})
}
The same negative radius definition is valid for clockwise spirals though both start and end radius must be negative, also the start and end angles must be defined accordingly as well. Here is an example code and Image result:
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\newcommand\bonusspiral{} % just for safety
\def\bonusspiral[#1](#2)(#3:#4)(#5:#6)[#7]{% \bonusspiral[draw options](placement)(start angle:end angle)(start radius:final radius)[revolutions]
\pgfmathsetmacro{\domain}{#4+#7*360}
\pgfmathsetmacro{\growth}{180*(#6-#5)/(pi*(\domain-#3))}
\draw [#1,
shift={(#2)},
domain=#3*pi/180:\domain*pi/180,
variable=\t,
smooth,
samples=int(\domain/5)] plot ({\t r}: {#5+\growth*\t-\growth*#3*pi/180})
}
\begin{document}
\begin{tikzpicture}
\bonusspiral[red](0,0)(60:270)(-1:-5)[2];
\draw (0,0) -- (240:1);
\draw (0,0) -- (-270:5);
\bonusspiral[blue](10,0)(20:60)(2:5)[5];
\draw (10,0) -- +(20:2);
\draw (10,0) -- +(60:5);
\end{tikzpicture}
\end{document}
The OP's graphic redesigned and with \spiral
!
Also used some new tricks to shorten up the code, the wings are still done by the plot coordinate
though.
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns}
\tikzset{dashed/.style={dash pattern=on 4pt off 1.5pt,line width=0.5pt},
wing/.style={smooth,line width=1pt,fill=black!5},
point/.style={circle,inner sep=0pt, minimum width=4pt,fill=black}
}
\newcommand\spiral{} % just for safety
\def\spiral[#1](#2)(#3:#4)(#5:#6)[#7]{%
\pgfmathsetmacro{\domain}{#4+#7*360}
\pgfmathsetmacro{\growth}{180*(#6-#5)/(pi*(\domain-#3))}
\draw [#1,
shift={(#2)},
domain=#3*pi/180:\domain*pi/180,
variable=\t,
smooth,
samples=int(\domain/5)] plot ({\t r}: {#5+\growth*\t-\growth*#3*pi/180})
}
\newcommand\intrado{(0,0)
(0.0334,-0.0767)
(0.1087,-0.1437)
(0.2253,-0.2011)
(0.3824,-0.2489)
(0.5790,-0.2870)
(0.8139,-0.3158)
(1.0860,-0.3355)
(1.3940,-0.3466)
(1.7365,-0.3497)
(2.1123,-0.3457)
(2.5199,-0.3356)
(2.9580,-0.3209)
(3.4252,-0.3029)
(3.9198,-0.2835)
(4.4427,-0.2625)
(4.9936,-0.2377)
(5.5666,-0.2102)
(6.1594,-0.1810)
(6.7696,-0.1513)
(7.3950,-0.1217)
(8.0332,-0.0930)
(8.6815,-0.0653)
(9.3376,-0.0386)
(9.9988,-0.0125)}
\newcommand\extrado{(0,0)
(0.0095,0.0831)
(0.0624,0.1691)
(0.1590,0.2574)
(0.2990,0.3467)
(0.4824,0.4357)
(0.7085,0.5225)
(0.9765,0.6050)
(1.2855,0.6812)
(1.6341,0.7488)
(2.0206,0.8055)
(2.4433,0.8492)
(2.8998,0.8778)
(3.3879,0.8897)
(3.9049,0.8833)
(4.4459,0.8592)
(5.0064,0.8210)
(5.5876,0.7687)
(6.1870,0.7023)
(6.8016,0.6219)
(7.4286,0.5277)
(8.0650,0.4197)
(8.7080,0.2980)
(9.3544,0.1623)
(10.0012,0.0125)}
\begin{document}
\begin{tikzpicture}[>=latex,scale=1,line width=0.5pt]
\begin{scope}[rotate around={-13:(10,0)}]
\draw[wing] plot coordinates {\intrado};
\draw[wing] plot coordinates {\extrado};
% points
\node[point] at (3,0) (EC) {};
\node[point] at (1.75,0) (AC) {};
\draw[dashed] (EC) -- +(-90:1)node[coordinate](ec){};
\draw[dashed] (AC) -- +(-90:1)node[coordinate](ec2){};
\node[above left, outer sep=4pt] at (EC) {$EC$};
\node[above left, outer sep=3pt] at (AC) {$AC$};
\spiral[](EC)(0:100)(0:0.5)[2] node[coordinate] (SpringEnd) {};
\draw[fill=white,white] (8.25,0) -- +(0:.5) arc (0:360:.5);
\draw[line width=1pt] (8.25,0) -- +(120:.5) arc (120:195:.5);
\fill[fill=white] (8,-.25) rectangle (10,.5);
% winglet
\begin{scope}[rotate around={-30:(8.3,0)},xshift=7.9cm,scale=0.35,y=1.5cm]
\draw[wing] plot coordinates {\intrado};
\draw[wing] plot coordinates {\extrado};
\end{scope}
\node[point] (kdelta) at (8.3,0) {};
\begin{scope}[rotate around={-30:(8.3,0)}]
\draw[dashed] (8.3,0) -- +(0:3.5) node[coordinate] (deltaEnd) {};
\draw[dashed] (8.3,0) -- +(-90:1.2) node[coordinate](epsC){};
\draw[dashed] (11.4,0) -- +(-90:1.2) node[coordinate](epsC2){};
\end{scope}
\draw[<->] (epsC) -- node[below left] {$\varepsilon c$}(epsC2);
\spiral[](kdelta)(0:130)(0:0.52)[2] node[above right] {$k_\delta$};
\draw[dashed](-1,0)--(12,0);
\draw[<-] (deltaEnd) arc [start angle=-30, delta angle=30, radius=3.5cm] node[midway,right]{$\delta$};
\end{scope}%
\draw[<->] (ec) -- node[below]{$ec$}(ec2);
\draw[->] (EC) +(180:3.5cm) arc [start angle=180, delta angle=-13, radius=3.5cm] node[midway,left]{$\alpha$};
\draw[dashed] (EC) -- +(180:4);
\node[yshift=2cm,pattern=north west lines,minimum width=2cm] (Ground) at (SpringEnd) {};
\draw[line width=1pt] (SpringEnd)-- node[right]{$k_\alpha$} (Ground.south);
\draw (Ground.south west) -- (Ground.south east);
\end{tikzpicture}
\end{document}
Going spiral crazy, a \spiral
tikz-like command!!
Reading How can I create new commands in TikZ? I got a little excited and thought of the old (and now deprecated) \bonusspiral
. I was not so fond of that fixed syntax, I much prefer the TikZ way, using comma separated lists and default values. So, I implemented the previous line of thought to a command that has very similar TikZ syntax:
\spiral[tikz options]{spiral options} ;
Where the spiral options are:
start radius = <num>, (default is 0)
end radius = <num>, (default is 1)
start angle = <degrees>, (default is 0)
end angle = <degrees>, (default is 0)
name = <text>, (defaul is nameless) % This is useful to have coordinates at start and end of spiral
revolutions = <num>, (default is 2)
center = {<coordinate>}, (default is (0,0)) % Equivalent to shift={<coordinate>}
sample rate = <degrees>, (default is 5) % Means: plot one point each <degrees>
clockwise (default is false) % This is used as boolean, when present spiral is clockwise
So, it is possible to readily define a spiral just saying \spiral{};
and it will follow the default values. To customize it, add the pertinant options. Important: most of the times connecting things is either needed or very helpful, the name
option (say name=myspiral
), when given, specifies two coordinates: (myspiralend)
and (myspiralstart)
, which as you can guess refer to the start and end position of the spiral! (spirals always start from the inside and end on the outside).
Knwon issues: as you may have noticed, it is not possible to inform units in the keys, so we are tied to the coordinate system units of tikz (default is cm
). A workaround for this is to use \begin{scope}[x=1<unit>,y=1<unit>]
, but you cannot say for instance start radius=1in
and end radius=5cm
(you'll get crazy results). When using \spiral{clockWise} node {A};
you'll get a node at the spiral's start position and if used node[at start]
you'll get a node at the spiral's center (this occurs even for non clockWise).
My last goal, to raise the done flag, was to make a spiral to=<coordinate>
option, that when given the spiral would go from its starting position to the specified <coodinate>
, following the other given instructions except for the end radius
, but it got somewhat complicated :(
.
The \spiral
definition (needs only tikz):
\makeatletter
\newif\ifspiral@is@clockwise
\pgfkeys{
spiral/.is family,
spiral,
start angle/.initial=0,
end angle/.initial=0,
start radius/.initial=0,
end radius/.initial=1,
revolutions/.initial=2,
name/.initial=,
center/.initial={(0,0)},
sample rate/.initial =5,
clockwise spiral/.is if=spiral@is@clockwise,
clockwise spiral/.default=false,
clockwise/.style={clockwise spiral=true},
default spiral/.style={start angle=0,end angle=0, start radius=0, end radius=1, revolutions=2, name=, center={(0,0)}, sample rate=5, clockwise spiral=false}
}
\newcommand\spiral[2][]{
\pgfkeys{spiral, default spiral,#2,
start angle/.get=\spiral@start@angle,
end angle/.get=\spiral@end@angle,
start radius/.get=\spiral@start@radius,
end radius/.get=\spiral@end@radius,
revolutions/.get=\spiral@revolutions,
name/.get=\spiral@name,
sample rate/.get=\spiral@sample@rate,
center/.get=\spiral@center
}
\def\spiral@start@name{}
\def\spiral@end@name{}
\ifspiral@is@clockwise
\renewcommand*{\spiral@start@angle}{\pgfkeysvalueof{/spiral/end angle}}
\renewcommand*{\spiral@end@angle}{\pgfkeysvalueof{/spiral/start angle}}
\renewcommand*{\spiral@start@radius}{\pgfkeysvalueof{/spiral/end radius}}
\renewcommand*{\spiral@end@radius}{\pgfkeysvalueof{/spiral/start radius}}
\if\relax\detokenize{\spiral@name}\relax
\else
\renewcommand*{\spiral@start@name}{\spiral@name end}
\renewcommand*{\spiral@end@name}{\spiral@name start}
\fi
\else
\if\relax\detokenize{\spiral@name}\relax
\else
\renewcommand*{\spiral@start@name}{\spiral@name start}
\renewcommand*{\spiral@end@name}{\spiral@name end}
\fi
\fi
\pgfmathsetmacro{\spiral@domain}{\spiral@end@angle+\spiral@revolutions*360}
\pgfmathsetmacro{\spiral@growth}{180*(\spiral@end@radius-\spiral@start@radius)/(pi*(\spiral@domain-\spiral@start@angle))}
\draw [#1,
shift={\spiral@center},
domain=\spiral@start@angle*pi/180:\spiral@domain*pi/180,
variable=\t,
smooth,
samples=int(\spiral@domain/\spiral@sample@rate)] node[coordinate,shift={(\spiral@start@angle:\spiral@start@radius)}](\spiral@start@name){} plot ({\t r}: {\spiral@start@radius+\spiral@growth*\t-\spiral@growth*\spiral@start@angle*pi/180}) node[coordinate](\spiral@end@name){}
}
\makeatother
A MWE
\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\spiral{center={(3,0)}, name=defaultspiral};
\node[above=0.6cm,align=center] at (defaultspiralstart) {This\\is the\\default spiral!};
\spiral{center={(5,0)}, clockwise, name=clockwisespiral};
\node[below=0.6cm,align=center] at (clockwisespiralstart) {This\\is a\\clockwise spiral!};
\spiral[blue, dashed]{start angle=45, end angle=90, start radius=1, end radius=2, revolutions=4, clockwise, name=sp1} node[at start]{At center};
\spiral[red, shift={(180:3.5)}]{end angle=45, end radius= 1, name=sp2} node[above left]{A custom spiral};
\foreach \sp in {defaultspiral,clockwisespiral,sp1,sp2}{
\fill[red!80!black] (\sp end) circle (1pt);
\fill[green!80!black] (\sp start) circle (1pt);
}
\end{tikzpicture}
\end{document}
Please report if any bugs are found.