Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have two nodes that I want and foci and I know what the sum of the distances should be (a constant times the distance between the focus nodes).

The way I know of drawing ellipses takes as parameters the center point and the major and minor axis.

I want to define another function (myellipse?) that takes as parameters the two nodes and the constant multiplier.

This is how I'm drawing them currently, doing all calculations by hand (example not perfect):

\draw [rotate around={-15:(1.8,0.5)}] (1.8,0.5) ellipse (2 and 1); 
share|improve this question
    
related: tex.stackexchange.com/questions/71548/… the command in my answer also works for ellipses –  cmhughes Oct 2 '12 at 23:23
    
@cmhughes I do not see how you connect this question with your answer... –  Paul Gaborit Oct 3 '12 at 0:35
    
@PaulGaborit the \pgfpatharcto can be drawn along an ellipse with an xradius and yradius –  cmhughes Oct 3 '12 at 3:36
    
@cmhughes You are right about \pgfpatharcto. But, here, the request is how to know (to calculate?) the first point, the target point, the center, the radii and the angle of rotation... –  Paul Gaborit Oct 3 '12 at 6:51
add comment

3 Answers 3

up vote 6 down vote accepted

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(\x2-\x1,\y2-\y1)}
    \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(\x2-\x1,\y2-\y1)}
    \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(\x2-\x1,\y2-\y1)}
    \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(\x2-\x1,\y2-\y1)}
    \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}
share|improve this answer
    
Nice! I had a version with the constant multiplier working as well. I did not know how to to use 'let', I like your solution. I ended up incorporating options in my solution with optional parameters. Thanks! –  Mig Oct 3 '12 at 4:01
    
Also, with your solution I'm able to name the node, cool! Extra question: How do I use the named nodes to clip a few ellipses and fill their intersection? –  Mig Oct 3 '12 at 20:23
1  
You can apply the clip option (without draw or fill operations) to an ellipse. –  Paul Gaborit Oct 3 '12 at 20:31
    
Yes, I tried that, but apparently the clipping doesn't hold outside of the command. Could you add an example? –  Mig Oct 3 '12 at 21:18
1  
@Mig You are right: clip action can't be applied to a node! A solution can use tex.stackexchange.com/a/72753/14500 to memoize ellipse path then to reuse it as clip. –  Paul Gaborit Oct 3 '12 at 21:52
show 2 more comments

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

share|improve this answer
add comment

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   
share|improve this answer
    
joli ( pretty ) –  rpapa Oct 3 '12 at 7:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.