Painting an ellipse that fits a row of node but is not narrow and long

Here's the "proper" way to do it: Adjust the ellipse shape. As it is, the circumscribing ellipse has the same height to width ratio H/W as the rectangle of nodes it circumscribes (A/B). In this case, H=sqrt(2)*A and B=sqrt(2)*W. This, of course, doesn't have to be that way. To get other aspect ratios that circumscribe a rectangle, you can scale the ratio using a factor c. The height and width of the ellipse then become H=sqrt(c^2+1)*A and W=sqrt(c^2+1)/c*B.

The code below declares a new shape called newellipse that will circumscribe a rectangle (or a set of nodes) just like the standard ellipse, but you can scale its height to width ratio using the key ellipse ratio. The code

\begin{tikzpicture}[
  every node/.style={draw},
  every newellipse node/.style={inner sep=0pt}
]
\path node (a) {A} -- ++(2cm,0) node (b) {B};
\node[fit=(a)(b), newellipse] {};
\node[fit=(a)(b), red, newellipse, ellipse ratio=2] {};
\node[fit=(a)(b), blue, newellipse, ellipse ratio=6] {};
\end{tikzpicture}

then yields

new ellipse with scale ratio

Here's the complete code. Only three lines are changed compared to the original ellipse shape, but unfortunately the whole \radius command has to be repeated.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fit,shapes.geometric}


\makeatletter

\pgfkeys{/pgf/.cd,
    ellipse ratio/.code={\pgfkeyssetvalue{/pgf/ellipse ratio}{#1}},
    ellipse ratio/.initial=1
}

\pgfdeclareshape{newellipse}
{
  \inheritsavedanchors[from=ellipse]
  \inheritanchorborder[from=ellipse]
  \savedanchor\radius{%
    % 
    % Caculate ``height radius''
    % 
    \pgf@y=.5\ht\pgfnodeparttextbox%
    \advance\pgf@y by.5\dp\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}%
    \advance\pgf@y by\pgf@yb%
    % 
    % Caculate ``width radius''
    % 
    \pgf@x=.5\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}%
    \advance\pgf@x by\pgf@xb%
    % 
    % Adjust
    %
    \pgfkeysgetvalue{/pgf/ellipse ratio}{\ratioscale}
    \pgfmathsetmacro\widthfactor{sqrt(\ratioscale^2+1)/\ratioscale}
    \pgfmathsetmacro\heightfactor{sqrt(\ratioscale^2+1)}
    \pgf@x=\widthfactor\pgf@x%
    \pgf@y=\heightfactor\pgf@y%
    % 
    % Adjust height, if necessary
    % 
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/minimum height}}%
    \ifdim\pgf@y<.5\pgf@yc%
      \pgf@y=.5\pgf@yc%
    \fi%
    % 
    % Adjust width, if necessary
    % 
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}%
    \ifdim\pgf@x<.5\pgf@xc%
      \pgf@x=.5\pgf@xc%
    \fi%
    % 
    % Add outer sep
    % 
    \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%  
    \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%  
    \advance\pgf@x by\pgf@xb%
    \advance\pgf@y by\pgf@yb%
  }

  \inheritanchor[from=ellipse]{center}
  \inheritanchor[from=ellipse]{mid}
  \inheritanchor[from=ellipse]{base}
  \inheritanchor[from=ellipse]{north}
  \inheritanchor[from=ellipse]{south}
  \inheritanchor[from=ellipse]{west}
  \inheritanchor[from=ellipse]{mid west}
  \inheritanchor[from=ellipse]{base west}
  \inheritanchor[from=ellipse]{north west}
  \inheritanchor[from=ellipse]{south west}
  \inheritanchor[from=ellipse]{east}
  \inheritanchor[from=ellipse]{mid east}
  \inheritanchor[from=ellipse]{base east}
  \inheritanchor[from=ellipse]{north east}
  \inheritanchor[from=ellipse]{south east}

  \inheritbackgroundpath[from=ellipse]
}
\makeatother


\begin{document}

\begin{tikzpicture}[
  every node/.style={draw},
  every newellipse node/.style={inner sep=0pt}
]
\path node (a) {A} -- ++(2cm,0) 
      node (b) {B};
\node[fit=(a)(b), newellipse] {};
\node[fit=(a)(b), red, newellipse, ellipse ratio=2] {};
\node[fit=(a)(b), blue, newellipse, ellipse ratio=6] {};
\end{tikzpicture}

\end{document}

Here's my original, somewhat more pragmatic answer:

You can adjust the inner xsep and inner ysep of the large ellipse independently, or use xscale and yscale:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fit,shapes.geometric}

\begin{document}

\begin{tikzpicture}[
  every node/.style={inner sep=1pt},
  proc/.style={shape=ellipse, draw}
]
\path node[proc] (q) {q} -- ++(2cm,0) 
      node[proc] (p1) {p$_1$} -- ++(1.5cm,0)
      node (d) {\ldots} -- ++(1.5cm,0)
      node[proc] (pn) {p$_n$};
\node[fit=(q)(p1)(d)(pn), proc, inner xsep=-3ex,inner ysep=2ex] {};
\node[fit=(q)(p1)(d)(pn), proc, red, xscale=0.75,yscale=2.5] {};
\end{tikzpicture}

\end{document}


My original answer is below the line. Here's a slightly improved version, which uses two "strategically-placed" pegs to distort the ellipse. I think this approach will need less manual fine tuning (of envel/inner sep and peg/node distance).

\begin{tikzpicture}[
  every node/.style={inner sep=1pt},
  proc/.style={shape=ellipse, draw},
  peg/.style={draw=none,color=black!0,node distance=1cm},
  envel/.style={shape=ellipse, draw, inner sep=-0.5cm}
]
\path node[proc] (q) {q} -- ++(2cm,0) 
      node[proc] (p1) {p$_1$} -- ++(1.5cm,0)
      node (d) {\ldots} -- ++(1.5cm,0)
      node[proc] (pn) {p$_n$};
\node  [peg,above of=p1] (c1) {+}; 
\node  [peg,below of=d] (c2) {+};
\node[fit=(q)(p1)(d)(pn)(c1)(c2), envel] {};
\end{tikzpicture}

Here's a slightly exaggerated answer. I suggest you play with the envel construction's inner sep and minimum height parameters to find what suits you best.

\begin{tikzpicture}[
  every node/.style={inner sep=1pt},
  proc/.style={shape=ellipse, draw},
  envel/.style={shape=ellipse, draw, inner sep=-0.5cm, minimum height=4.5cm}
]
\path node[proc] (q) {q} -- ++(2cm,0) 
      node[proc] (p1) {p$_1$} -- ++(1.5cm,0)
      node (d) {\ldots} -- ++(1.5cm,0)
      node[proc] (pn) {p$_n$};
\node[fit=(q)(p1)(d)(pn), envel] {};
\end{tikzpicture}

A PSTricks solution with the following macro syntex:

\Ellipse(<x_centre>,<y_centre>)(<width>,<height>){<label>}

Here is the code:

\documentclass{article}

\usepackage{pstricks}
\def\Ellipse(#1,#2)(#3,#4)#5{\psellipse(#1,#2)(#3,#4)\rput(#1,#2){#5}}

\begin{document}

\begin{pspicture}(8,2)
  \psellipse(4,1)(4,1)
  \Ellipse(1,1)(0.5,0.3){$p_{1}$}
  \Ellipse(3,1)(0.5,0.3){$p_{2}$}
  \Ellipse(5,1)(0.5,0.3){$\dots$}
  \Ellipse(7,1)(0.5,0.3){$p_{n}$}
\end{pspicture}

\end{document}

output

Tags:

Tikz Pgf

Fit