绘制一个适合一行节点但不窄也不长的椭圆

绘制一个适合一行节点但不窄也不长的椭圆

我想绘制一个 Tikz 图,其中一个椭圆包含一行较小的椭圆。我尝试使用拟合库来执行此操作:

\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] {};
\end{tikzpicture}

结果是一个狭长的椭圆:

坏椭圆

我希望周围的椭圆更短更高,即末端更靠近和q节点pn,并且高度也略高一些。正确的配置是什么?

答案1

我最初的答案低于这个数字。这是一个略微改进的版本,它使用两个“策略性放置”的钉子来扭曲椭圆。我认为这种方法需要更少的手动微调(和envel/inner seppeg/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}

这是一个略显夸张的答案。我建议你尝试一下envel构造inner sepminimum height参数,找到最适合你的。

\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}

答案2

这是“正确”的做法:调整形状ellipse。实际上,外接椭圆的高宽比H/W与它外接的节点矩形相同(A/B)。在这种情况下,H=sqrt(2)*AB=sqrt(2)*W。当然,这不一定非得是那样。要获得外接矩形的其他纵横比,可以使用因子 缩放该比率c。然后椭圆的高度和宽度变为H=sqrt(c^2+1)*AW=sqrt(c^2+1)/c*B

下面的代码声明了一个名为 的新形状newellipse,它将像标准椭圆一样外接一个矩形(或一组节点),但你可以使用 键缩放其高宽比ellipse ratio。代码

\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}

然后产生

具有比例的新椭圆

这是完整的代码。与原始形状相比,只有三行更改ellipse,但不幸的是整个\radius命令必须重复。

\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}

以下是我原来的、更务实的回答:

您可以单独调整大椭圆的inner xsep和,或者使用和:inner ysepxscaleyscale

\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}

答案3

具有以下宏语法的 PSTricks 解决方案:

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

以下是代码:

\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}

输出

相关内容