# How to draw an elliptical arc in TikZ given only opposite extreme points (vertices) of the ellipse?

Given two nodes (a) and (b), I would like to draw an elliptical arc from (a) to (b) whose major axis is the segment connecting (a) and (b) (the minor axis can be some arbitrary length). The main difficulty is that this ellipse's axes need not be parallel to the standard coordinate axes. Moreover, I don't know what angle the point (b) is at relative to (a).

What I have done so far is to, within a scope, shift the origin of tikz's coordinate system to the midpoint between (a) and (b), and change the coordinate x-vector to (a), with the plan of just drawing a plain old elliptical arc starting at (1,0) from 0 degrees to 180 degrees in this new coordinate system.

The following example is the picture I'm trying to draw with almost everything stripped away, but I left in how I am making the points (a) and (b) to illustrate why I don't know their coordinates.

\documentclass[11pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage{amsmath,amssymb,amsthm,amsfonts,graphicx}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.markings,positioning}

\begin{document}
\begin{center}
\begin{tikzpicture}

\draw[postaction={decorate,decoration={markings,
mark=at position 0.7 with {\node (a) {};}}}]
(0,0) ellipse (0.6 and 0.4);

\draw[postaction={decorate,decoration={markings,
mark=at position 0.7 with {\node (b) {};}}}]
(0,0) ellipse (1.2 and 1);

\node (c) at ($(a)!0.5!(b)$) {};

\begin{scope}[shift={(c)},x={(a)}]
\draw (1,0) arc (0:180:1 and 0.3);
\draw[dashed] (-1,0) arc (180:360:1 and 0.3);
\end{scope}
\end{tikzpicture}
\end{center}
\end{document}


This produces (I want the ellipse I'm drawing to lie within the annulus, i.e. each extreme point should be tangent to the inner or outer pieces, respectively.)

By way of comparison, if instead of trying to make an ellipse, I just draw a line from (-1,0) to (1,0) in my new coordinate system, by changing the contents of my scope to

\begin{scope}[shift={(c)},x={(a)}]
\draw (-1,0) -- (1,0);
\end{scope}


then things work in the manner I want: This works because it did not require using any y-coordinates.

Unfortunately, I don't know what vector I should change the coordinate y-vector to. If there is an easy way to determine a perpendicular bisector of the segment connecting (a) and (b), so that I can change the coordinate y-vector to it, that would be great, but I'd appreciate any other approaches to solving this issue.

• Well, how would you mathematically compute the equation of the ellipse given two points? I think that is the place to start. Also, It would be helpful if you composed a fully compilable MWE including \documentclass and the appropriate packages that shows what you have done so far. While solving problems is fun, setting them up is not. Then those trying to help can simply cut and paste your MWE and get started on solving problem. – Peter Grill Nov 13 '12 at 5:27
• Thanks for your suggestions. I've added the code I've been working with. – Zev Chonoles Nov 13 '12 at 6:02
• The midpoint of (a) and (b) is (a)!0.5!(b). – Peter Grill Nov 13 '12 at 6:04
• My compiler throws an error if I don't put it in the "calc" format of parentheses around dollar signs. – Zev Chonoles Nov 13 '12 at 6:06
• No; the issue is that in my scope, the y-vector is still vertical, instead of being perpendicular to the new x-vector I declared, so that an ellipse is drawn in a skewed way. The way I was hoping to draw my ellipse was to come up with the right d so that adding y={(d)} to my scope will make an orthogonal coordinate system such that my extreme points lie on the x-axis of this coordinate system, and such that the y-axis is perpendicular to the x-axis (so that shapes will be drawn correctly). – Zev Chonoles Nov 13 '12 at 6:14

I think that this problem is quite different that what the title implies. If you are are not doing these kind of figure often, you can just apply a scale=0.7 to yield the desired result: ## Code:

\documentclass[11pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage{amsmath,amssymb,amsthm,amsfonts,graphicx}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.markings,positioning}

\begin{document}
\begin{center}
\begin{tikzpicture}

\draw[postaction={decorate,decoration={markings,
mark=at position 0.7 with {\node (a) {};}}}]
(0,0) ellipse (0.6 and 0.4);

\draw[postaction={decorate,decoration={markings,
mark=at position 0.7 with {\node (b) {};}}}]
(0,0) ellipse (1.2 and 1);

\node (c) at ($(a)!0.5!(b)$) {};

\begin{scope}[red, shift={(c)},x={(a)}, scale=0.7]
\draw (1,0) arc (0:180:1 and 0.3);
\draw[dashed] (-1,0) arc (180:360:1 and 0.3);
\end{scope}
\end{tikzpicture}
\end{center}
\end{document}


Here is my humble attempt from what I understood from your question. Warning: the code is ugly. Please clean to your liking.

The thing is you have to get the x and y coordinates of the points. To do this, I (shamefully) borrowed Andrew Stacey's \gettikzxy macro from Extract x, y coordinate of an arbitrary point in TikZ.

Regarding

(the minor axis can be some arbitrary length). The main difficulty is that this ellipse's axes need not be parallel to the standard coordinate axes.

We can use a distance modifier

\coordinate (d) at ($(c)!0.75cm!90:(b)$);


Here, 0.75cm is the dimension of the minor axis of the elipse and 90 is the angle it makes with the line connecting nodes c and b.

We also need to store the dimension of the semi-major axis and semi-minor axis. The following code snippet takes care of this.

\pgfmathsetmacro{\Minb}{\dx-\cx}%
\pgfmathsetmacro{\Majb}{\bx-\cx}%


To draw the ellipse, we use the \pgfpathellipse macro. The syntax is

\pgfpathellipse{<center>}{<first axis>}{<second axis>}


where <first axis> and <second axis> are the axis vectors.

Putting it all together we get

## Code

\documentclass[tikz]{standalone}

\usetikzlibrary{calc}

\makeatletter
\newcommand{\gettikzxy}{%
\tikz@scan@one@point\pgfutil@firstofone#1\relax
\edef#2{\the\pgf@x}%
\edef#3{\the\pgf@y}%
}
\makeatother
\begin{document}
\begin{tikzpicture}
%\draw (0,0) grid (3,3);
\coordinate (a) at (0,0); % one point
\coordinate (b) at (3,3); % the other point
\coordinate (c) at ($(a)!.5!(b)$); % center
\coordinate (d) at ($(c)!0.75cm!90:(b)$); % the coordinate of one end of the minor axis
\coordinate (e) at ($(c)!.8!(b)$); % coordinate of one end of the major axis for the second ellipse. Adjust .8 to your liking
\coordinate (f) at ($(c)!.5!(d)$); % coordinate of one end of the minor axis for the second ellipse
\coordinate (g) at ($(d)!.5!(f)$);
%% Getting the x and y coordinates
\gettikzxy{(b)}{\bx}{\by}
\gettikzxy{(c)}{\cx}{\cy}
\gettikzxy{(d)}{\dx}{\dy}
\gettikzxy{(e)}{\ex}{\ey}
\gettikzxy{(f)}{\fx}{\fy}
%% Getting the values of the axes vectors
\pgfmathsetmacro{\Minb}{\dx-\cx}%
\pgfmathsetmacro{\Majb}{\bx-\cx}%
\pgfmathsetmacro{\Mins}{\fx-\cx}%
\pgfmathsetmacro{\Majs}{\ex-\cx}%
%% Drawing the ellipses
{%\color{red}
\pgfpathellipse{\pgfpoint{\cx}{\cy}}
{\pgfpoint{\Majb}{\Majb}}
{\pgfpoint{-\Minb}{\Minb}}
\pgfusepath{draw}}
{%\color{blue}
\pgfpathellipse{\pgfpoint{\cx}{\cy}}
{\pgfpoint{\Majs}{\Majs}}
{\pgfpoint{-\Mins}{\Mins}}
\pgfusepath{draw}}
%\foreach \letter in {a,b,c,d}
%   \fill (\letter) circle (2pt) node [above] {\letter};

%% Integrating Peter Grill's suggested scaling
\begin{scope}[red, shift={(g)},x={(c)}, scale=0.3]
\draw (1,0) arc (0:180:1 and 0.3);
\draw[dashed] (-1,0) arc (180:360:1 and 0.3);
\end{scope}
\end{tikzpicture}
\end{document}


## Output • All code borrowing should be absolutely and utterly shameless! – Andrew Stacey Nov 15 '12 at 13:32