The problem with getting the arc to cover the right portion of the ellipse is that the start angle
and end angle
are assumed to be angles on the edge of a circle, not on the edge of an ellipse. In this application, an ellipse is basically a squashed circle. The angle you're calculating is too large, since you're implicitly assuming that points on the circle are projected radially onto the ellipse:
I've written a new TikZ key correct ellipse angles
that corrects the start and end angles according to the x radius
and y radius
of the ellipse. It lets you write
\draw [fill=lightgray!50]
(top-2) -- (top-1) let \p1 = (top-1) in
arc [x radius=2, y radius=4, start angle=\angleorigr, end angle=\angleendr, correct ellipse angles]
-- (bottom-2) -- (bottom-1)
arc [x radius=2, y radius=4, start angle=\angleorigl, end angle=\angleendl, correct ellipse angles=360 ]
;
to give
The optional parameter can be used to correct for negative angles that would lead to the arc going the wrong way.
Here's the complete code:
\documentclass[border=5pt]{standalone}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usetikzlibrary{intersections}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}[every text node part/.style={font=\footnotesize},
>=latex]
\draw (0, 0) [dashed, name path=footprint] circle [x radius=2, y radius=4];
\path [name path=top slice] (-2, 1) -- (2, 1);
\path [name path=bottom slice] (-2, -1) -- (2, -1);
\path [name intersections={of=footprint and {top slice}, name=top}];
\path [name intersections={of=footprint and {bottom slice},
name=bottom}];
\pgfmathanglebetweenpoints{%
\pgfpointorigin}{%
\pgfpointanchor{top-1}{center}}
\let\angleorigr\pgfmathresult
\pgfmathanglebetweenpoints{%
\pgfpointorigin}{%
\pgfpointanchor{bottom-2}{center}}
\pgfmathsetmacro{\angleendr}{\pgfmathresult}
\pgfmathanglebetweenpoints{%
\pgfpointorigin}{%
\pgfpointanchor{top-2}{center}}
\let\angleendl\pgfmathresult
\pgfmathanglebetweenpoints{%
\pgfpointorigin}{%
\pgfpointanchor{bottom-1}{center}}
\pgfmathsetmacro{\angleorigl}{\pgfmathresult}
\makeatletter
\tikzset{
correct ellipse angles/.code={
\pgfkeysgetvalue{/tikz/start angle}\start@angle
\pgfkeysgetvalue{/tikz/end angle}\end@angle
\pgfmathsetmacro\corrected@startangle{atan2(cos(\start@angle)/\pgfkeysvalueof{/tikz/x radius},sin(\start@angle)/\pgfkeysvalueof{/tikz/y radius})}
\pgfmathsetmacro\corrected@endangle{atan2(cos(\end@angle)/\pgfkeysvalueof{/tikz/x radius},sin(\end@angle)/\pgfkeysvalueof{/tikz/y radius})}
\tikzset{/tikz/start angle=\corrected@startangle+#1, end angle=\corrected@endangle}
},
correct ellipse angles/.default=0
}
\makeatother
\draw [fill=lightgray!50]
(top-2) -- (top-1) let \p1 = (top-1) in
arc [x radius=2, y radius=4, start angle=\angleorigr, end angle=\angleendr, correct ellipse angles]
-- (bottom-2) -- (bottom-1)
arc [x radius=2, y radius=4, start angle=\angleorigl, end angle=\angleendl, correct ellipse angles=360 ]
;
\end{tikzpicture}
\begin{tikzpicture}
\draw ellipse [x radius=2cm, y radius=2cm];
\draw (2cm,0pt) -- (0,0) -- (63:2cm) (0,0) -- (45:2cm);
\draw [line width=6pt,opacity=0.5,orange] (2cm, 0pt) arc [x radius=2cm, y radius=2cm, start angle=0, end angle=63];
\draw [line width=6pt,opacity=0.5,cyan] (2.2cm, 0pt) arc [x radius=2.2cm, y radius=2.2cm, start angle=0, end angle=45];
\fill [blue,x=1cm,y=1cm] (1.41,1.41) circle [radius=2pt];
\draw ellipse [x radius=1cm, y radius=2cm];
\draw [line width=6pt,opacity=0.5,orange] (1cm, 0pt) arc [x radius=1cm, y radius=2cm, start angle=0, end angle=63];
\draw [line width=6pt,opacity=0.5,cyan] (1.2cm, 0pt) arc [x radius=1.2cm, y radius=2.2cm, start angle=0, end angle=45];
\fill [red,x=0.5cm,y=1cm] (1.41,1.41) circle [radius=2pt];
\node at (60:2cm) [pin={[text width=3cm]75:You're measuring\\this angle\ldots}] {};
\node at (25:2.2cm) [pin={[text width=3cm]75:\ldots but you want this one}] {};
\end{tikzpicture}
\end{document}
Here is an answer, using the technique described here, with more detail,
\pgfmathsetmacro{\ex}{0}
\pgfmathsetmacro{\ey}{1}
\draw (\ex,\ey) -- ++(-15:1)
(\ex,\ey) -- ++(15:1);
\draw (\ex,\ey) ++(45:.8) arc (45:-45:.8);
The secret to this is in the last line,
\draw (\ex,\ey) ++(45:.8)
Jumps the draw cursor to "the 45 degree position on a circle of radius 0.8", without drawing anything (achieved by using only ++ and not any -- in the command)
Then, from there, we draw an arc
arc (45:-45:.8);
from 45 degrees to -45 degrees, of what would be a circle of radius .8.
Pretty roundabout way to do this, but still it works fine.
Edit:
My finished eye:
\begin{tikzpicture}
%eye
\pgfmathsetmacro{\eyeSize}{1}
\pgfmathsetmacro{\ex}{0}
\pgfmathsetmacro{\ey}{1}
\pgfmathsetmacro{\eRot}{-10}
\pgfmathsetmacro{\eAp}{-55}
\draw[rotate around={\eRot:(\ex,\ey)}] (\ex,\ey) -- ++(-.5*\eAp:\eyeSize)
(\ex,\ey) -- ++(.5*\eAp:\eyeSize);
\draw (\ex,\ey) ++(\eRot+\eAp:.75*\eyeSize) arc (\eRot+\eAp:\eRot-\eAp:.75*\eyeSize);
% IRIS
\draw[fill=gray] (\ex,\ey) ++(\eRot+\eAp/3:.75*\eyeSize) % start point
arc (\eRot+180-\eAp:\eRot+180+\eAp:.28*\eyeSize);
%PUPIL, a filled arc
\draw[fill=black] (\ex,\ey) ++(\eRot+\eAp/3:.75*\eyeSize) % start point
arc (\eRot+\eAp/3:\eRot-\eAp/3:.75*\eyeSize);
\end{tikzpicture}
Best Answer
You can use path decorations: