我想绘制一个 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 sep
)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}
这是一个略显夸张的答案。我建议你尝试一下envel
构造inner sep
和minimum 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)*A
和B=sqrt(2)*W
。当然,这不一定非得是那样。要获得外接矩形的其他纵横比,可以使用因子 缩放该比率c
。然后椭圆的高度和宽度变为H=sqrt(c^2+1)*A
和W=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 ysep
xscale
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}
答案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}