Draw an ellipse from the two focus points (foci) and the sum of the distances from foci to border

Third Edit: A simpler solution without node or memoization... The result is the same as the second edit (see below) but without labels.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand\ellipsebyfoci[4]{% options, focus pt1, focus pt2, cste
  \path[#1] let \p1=(#2), \p2=(#3), \p3=($(\p1)!.5!(\p2)$)
  in \pgfextra{
    \pgfmathsetmacro{\angle}{atan2(\y2-\y1,\x2-\x1)}
    \pgfmathsetmacro{\focal}{veclen(\x2-\x1,\y2-\y1)/2/1cm}
    \pgfmathsetmacro{\lentotcm}{\focal*2*#4}
    \pgfmathsetmacro{\axeone}{(\lentotcm - 2 * \focal)/2+\focal}
    \pgfmathsetmacro{\axetwo}{sqrt((\lentotcm/2)*(\lentotcm/2)-\focal*\focal}
  }
  (\p3) ellipse[x radius=\axeone cm,y radius=\axetwo cm, rotate=\angle];
}

\begin{document}
\begin{tikzpicture}
  \coordinate (a) at (0,0);
  \coordinate (b) at (5,3);
  \ellipsebyfoci{draw,fill=cyan!50}{a}{b}{1.4}
  \begin{scope}
    \ellipsebyfoci{clip}{a}{b}{1.4}
    \ellipsebyfoci{draw,fill=orange!50,name=ell 2}{0,0}{3,5}{1.05}
    \fill[red] (a) circle(2pt);
    \fill[red] (b) circle(2pt);
  \end{scope}
\end{tikzpicture}
\end{document}

Second Edit: Here is a solution with an example of clipped ellipse (using my answer to Best way to draw scaled polygons in tikz just to memoize path of ellipse node).

enter image description here

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.geometric,decorations.pathreplacing}

\makeatletter
% to produce automaticaly homothetic paths
\newcounter{homothetypoints} % number of vertices of path
\tikzset{
  % homothety is a family...
  homothety/.style={homothety/.cd,#1,/tikz/.cd},
  % ...with some keys
  homothety={
    % parameters
    scale/.store in=\homothety@scale,% scale of current homothetic transformation
    center/.store in=\homothety@center,% center of current homothetic transformation
    name/.store in=\homothety@name,% prefix for named vertices
    % default values
    scale=1,
    center={0,0},
    name=homothety,
    % initialization
    init memoize homothetic path/.code={
      \xdef#1{}
      \setcounter{homothetypoints}{0}
    },
    % incrementation
    ++/.code={\addtocounter{homothetypoints}{1}},
    % a style to store an homothetic transformation of current path into #1 macro
    store in/.style={
      init memoize homothetic path=#1,
      /tikz/postaction={
        decorate,
        decoration={
          show path construction,
          moveto code={
            % apply homothetic transformation to this segment and add result to #1
            \xdef#1{#1 ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentfirst)$)}
            % name this vertex
            \coordinate[homothety/++](\homothety@name-\arabic{homothetypoints})
            at ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentfirst)$);
          },
          lineto code={
            % apply homothetic transformation to this segment and add result to #1
            \xdef#1{#1 -- ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$)}
            % name this vertex
            \coordinate[homothety/++] (\homothety@name-\arabic{homothetypoints})
            at ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$);
          },
          curveto code={
            % apply homothetic transformation to this segment and add result to #1
            \xdef#1{#1
              .. controls ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentsupporta)$)
              and ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentsupportb)$)
              .. ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$)}
            % name this vertex
            \coordinate[homothety/++] (\homothety@name-\arabic{homothetypoints})
            at ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$);
          },
          closepath code={
            % apply homothetic transformation to this segment and add result to #1
            \xdef#1{#1 -- cycle ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$)}
          },
        },
      },
    },
  },
}
\makeatother

\newcommand\ellipsebyfoci[4]{% options, focus pt1, focus pt2, cste
  \path let \p1=(#2), \p2=(#3), \p3=($(\p1)!.5!(\p2)$)
  in \pgfextra{
    \pgfmathsetmacro{\angle}{atan2(\y2-\y1,\x2-\x1)}
    \pgfmathsetmacro{\focal}{veclen(\x2-\x1,\y2-\y1)/2/1cm}
    \pgfmathsetmacro{\lentotcm}{\focal*2*#4}
    \pgfmathsetmacro{\axeone}{(\lentotcm - 2 * \focal)/2+\focal}
    \pgfmathsetmacro{\axetwo}{sqrt((\lentotcm/2)*(\lentotcm/2)-\focal*\focal}
  }
  (\p3) node[#1,inner sep=0,rotate=\angle,ellipse,minimum width=2*\axeone cm,minimum height=2*\axetwo cm]{};
}

\begin{document}
\begin{tikzpicture}
  \coordinate (a) at (0,0);
  \coordinate (b) at (5,3);
  \ellipsebyfoci{draw,fill=cyan!50,name=ell 1,homothety={store in=\mypath}}{a}{b}{1.4}
  \node[fill=white] at (ell 1.south){1.4};
  \begin{scope}
    \clip \mypath;
    \ellipsebyfoci{draw,fill=orange!50,name=ell 2}{0,0}{3,5}{1.05}
    \node[fill=white] at (ell 2.south){1.05};
    \fill[red] (a) circle(2pt);
    \fill[red] (b) circle(2pt);
  \end{scope}
\end{tikzpicture}
\end{document}

First Edit: Here is a solution with the constant multiplier as required (see below for explanations).

enter image description here

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.geometric}
\begin{document}

\newcommand\ellipsebyfoci[4]{% options, focus pt1, focus pt2, cste
  \path let \p1=(#2), \p2=(#3), \p3=($(\p1)!.5!(\p2)$)
  in \pgfextra{
    \pgfmathsetmacro{\angle}{atan2(\y2-\y1,\x2-\x1)}
    \pgfmathsetmacro{\focal}{veclen(\x2-\x1,\y2-\y1)/2/1cm}
    \pgfmathsetmacro{\lentotcm}{\focal*2*#4}
    \pgfmathsetmacro{\axeone}{(\lentotcm - 2 * \focal)/2+\focal}
    \pgfmathsetmacro{\axetwo}{sqrt((\lentotcm/2)*(\lentotcm/2)-\focal*\focal}
  }
  (\p3) node[#1,inner sep=0,rotate=\angle,ellipse,minimum width=2*\axeone cm,minimum height=2*\axetwo cm]{};
}

\begin{tikzpicture}
  \coordinate (a) at (0,0);
  \coordinate (b) at (5,3);
  \ellipsebyfoci{draw,fill=cyan!50,name=ell 1}{a}{b}{1.4}
  \node[fill=white] at (ell 1.south){1.4};
  \ellipsebyfoci{draw,fill=orange!50,name=ell 2}{a}{b}{1.05}
  \node[fill=white] at (ell 2.south){1.05};
  \fill[red] (a) circle(2pt);
  \fill[red] (b) circle(2pt);
\end{tikzpicture}
\end{document}

First answer: Here is a solution with a node shaped as ellipse (via shapes.geometric library).

I define the \ellipsebyfoci macro with four arguments:

  1. options for the ellipse (to draw it, to fill it, etc.),
  2. first focus pt,
  3. second focus pt,
  4. sum of distance between foci and border.

All calculations are in centimeters to avoid overflows (! Dimension too large.).

enter image description here

The code:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.geometric}

\newcommand\ellipsebyfoci[4]{% options, focus pt1, focus pt2, sum
  \path let \p1=(#2), \p2=(#3), \p3=($(\p1)!.5!(\p2)$)
  in \pgfextra{
    \pgfmathsetmacro{\angle}{atan2(\y2-\y1,\x2-\x1)}
    \pgfmathsetmacro{\focal}{veclen(\x2-\x1,\y2-\y1)/2/1cm}
    \pgfmathsetmacro{\lentotcm}{#4/1cm}
    \pgfmathsetmacro{\axeone}{(\lentotcm - 2 * \focal)/2+\focal}
    \pgfmathsetmacro{\axetwo}{sqrt((\lentotcm/2)*(\lentotcm/2)-\focal*\focal}
  }
  (\p3) node[#1,inner sep=0,rotate=\angle,ellipse,minimum width=2*\axeone cm,minimum height=2*\axetwo cm]{};
}

\begin{document}
\begin{tikzpicture}
  \coordinate (a) at (0,0);
  \coordinate (b) at (7,3);

  \fill[red] (a) circle(2pt);
  \fill[red] (b) circle(2pt);

  \ellipsebyfoci{draw,fill=orange,fill opacity=.1}{a}{b}{8cm}
\end{tikzpicture}
\end{document}

I got what I wanted! Not sure if there is a better way to do it though...

\makeatletter   
\newcommand*{\myellipse}[3]{
  % Bigger axis: #3
  % Smaller axis: sqrt([#3]ˆ2 - |uv|ˆ2)
  \coordinate (midpoint) at ($(#1)!0.5!(#2)$) {};

  % Calculate angle
  \pgfmathanglebetweenpoints{\pgfpointanchor{#1}{center}}
                            {\pgfpointanchor{#2}{center}}
  \let\angle\pgfmathresult % save result in \angle 


  % calculate distance
  \pgfpointdiff{\pgfpointanchor{#1}{center}}
               {\pgfpointanchor{#2}{center}}
  \pgf@xa=\pgf@x % no need to use a new dimen
  \pgf@ya=\pgf@y
  \pgfmathparse{veclen(\pgf@xa,\pgf@ya)/28.45274} %  to convert from                      % pt to cm 
  \let\uv\pgfmathresult % save the result in \uv

  \draw [rotate around={\angle:(midpoint)}] 
        (midpoint) ellipse ({#3} and {sqrt((#3)*(#3) - (\uv)*(\uv))}); 
}
\makeatother   

this example is not a complete answer but just an outline of a point by point calculation of the ellipse from Tikz tools, this is certainly not optimal

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections}

\begin{document}
\begin{tikzpicture}

\begin{scope}[rotate=15]
\def\entraxe{200}
\draw (0,0)coordinate(A) -- (\entraxe/100,0)coordinate(B);
\foreach \rr in {101,102,103,...,299}{
\path[red,name path =circleA] (A) circle (\rr/100);
\path[blue,name path =circleB] (B) circle ({(400-\rr)/100});
\path[dashed,name intersections={of=circleA and circleB}];
\draw (intersection-1) circle (0.01cm);
\draw (intersection-2) circle (0.01cm);
}
\end{scope}

\end{tikzpicture}
\end{document}

enter image description here

Tags:

Tikz Pgf