我需要一些帮助,使用 TiKz 绘制框图。
我想要画一些类似的东西:
然而,到目前为止,我还在努力取得进一步的进步:
使用下面的代码:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,positioning,patterns,decorations.pathmorphing}
\begin{document}
\tikzstyle{block} = [draw, rectangle, minimum size=5em]
\tikzstyle{joint} = [draw, circle, minimum size=1em]
\begin{tikzpicture}[>=stealth, auto, node distance=2cm]
% Place nodes
\node [block] (system) {System};
\node [coordinate, left=of system] (infork) {};
\node [coordinate, left=of infork] (input) {};
\node [coordinate, right=of system] (outfork) {};
\node [coordinate, right=of outfork] (output) {};
\node [coordinate, above=of system] (disturbances) {};
\node [block, below=of system] (model) {Model};
\node [joint, right=of model] (sum) {};
\node [coordinate, right=of sum] (error) {};
% Connect nodes
\draw [->, decorate, decoration={snake, post length=1mm}] (disturbances) -- node {\(d'\)} (system);
\draw [->] (input) -- node {\(u'\)} (system);
\draw [->] (system) -- node {\(t'\)} (output);
\draw [->] (model) -- node {\(y\)} (sum);
\draw [->] (sum) -- node {\(\epsilon\)} (error);
\draw [->] (infork) |- node {\(u\)} (model);
\draw [->] (outfork) -- node {\(t\)} (sum);
\end{tikzpicture}
\end{document}
也就是说,我想找到如何:
在两个块之间放置一个矩形
Measurement
。最好,这个矩形将填充浅灰色,并以虚线为边框。注意:我不介意矩形覆盖垂直线。我只是希望它们保持垂直方向将圆圈放在
sum
叉子的正后方,以便有一条垂直线连接t'
到这个圆圈将
u
和t
正确放置(例如像第一张图片中那样)在箭头与圆圈相交的地方有
+
和符号-
答案1
这里的所有答案都无法捕捉到原始手绘的外观。以下是 Metapost 的解决方案,它使用mp-草图以获得手绘效果。我还使用了 Comic Neue 和 Euler 字体。结果如下:
\usetypescriptfile[euler]
\definetypeface[mainfont][rm][specserif][ComicNeue][default]
\definetypeface[mainfont][mm][math] [pagellaovereuler][default]
\setupbodyfont[mainfont,12pt]
% Set upright style for Euler Math
\appendtoks \rm \to \everymathematics
\setupmathematics
[lcgreek=normal, ucgreek=normal]
\startMPinclusions
input rboxes;
input mp-sketch;
\stopMPinclusions
\defineframed
[labelframe]
[
background=color,
backgroundcolor=gray,
frame=off,
]
\starttext
\startMPpage[offset=3mm]
sketchypaths;
defaultdx := 16bp;
defaultdy := 16bp;
circmargin := 5bp;
sketch_amount := 2bp;
u := 1cm;
drawoptions(withpen pencircle scaled 1bp);
boxit.system("SYSTEM");
boxit.model ("MODEL");
circleit.adder("$\cdot$");
system.c = origin;
system.s - model.n = (0, 3u);
z.0 = system.w - (2u, 0);
z.1 = 0.5[ z.0, system.w ];
z.2 = (x.1, ypart model.w);
z.3 = system.e + (u, 0);
z.4 = system.e + (2u, 0);
z.5 = (x.4, y.2);
adder.c = (x.3, ypart model.c);
drawboxed(system, model, adder);
z.6 = 0.5[system.s, model.n];
stripe_path_n
(withpen pencircle scaled 2 withcolor 0.5white)
(draw)
fullsquare xyscaled(x.3 - x.1 + u, 2*LineHeight)
shifted z.6 dashed evenly;
label("\labelframe{Measurement}", z.6);
% Reduce the amount of randomness for the lines
sketch_amount := bp;
drawarrow z.0 -- lft system.w;
drawarrow z.1 -- z.2 -- lft model.w;
drawarrow system.e -- z.4 ;
drawarrow model.e -- lft adder.w ;
drawarrow z.3 -- top adder.n ;
drawarrow adder.e -- z.5 ;
label.urt("$-$", adder.n);
label.llft("$+$", adder.w);
label.top("$u'$", z.1);
label.top("$t'$", z.3);
label.top("$ε$", 0.5[adder.e, z.5]);
dx := 12bp;
label.urt("$t$", adder.n + (0, dx));
label.urt("$u$", z.2 + (0, dx));
\stopMPpage
\stoptext
答案2
这就是您所寻找的吗?
修复:
- 添加了一个节点,
Measurement
将其定位在节点中间System
,并Model
使用以下语法:\node ... at ($(system)!.5!(model)$) {};
。这需要calc
添加到 Tikz 库中。 - 将对角线路径更改为,
\draw [->] (outfork) -| (sum.north) node [very near end] {\(t\)};
以便节点恰好停止在总和的北点。 - 上述
[very near end]
操作确保节点看起来非常靠近箭头尖端。 - 删除
minimal size
使节点看起来是正方形的(有点丑),并用inner sep
在节点内部一致添加空间的节点替换它,以便矩形边框与节点文本的距离相等。 - 对于节点
u
(左边的路径),我添加了键,[anchor=south west]
以便它向右向上移动一点并出现在路径旁边。 - 使用标签作为
-
和+
符号。最初它们是节点,但这样看起来更好,并且代码更简洁、更短。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,positioning,patterns,decorations.pathmorphing,calc}
\begin{document}
\tikzstyle{block} = [draw, rectangle, inner sep=6pt]
\tikzstyle{joint} = [draw, circle,minimum size=1em]
\begin{tikzpicture}[>=stealth, auto, node distance=2cm]
% Place nodes
\node [block] (system) {System};
\node [coordinate, left=of system] (infork) {};
\node [coordinate, left=of infork] (input) {};
\node [coordinate, right=of system] (outfork) {};
\node [coordinate, right=of outfork] (output) {};
\node [coordinate, above=of system] (disturbances) {};
\node [block, below=of system] (model) {Model};
\node [joint, right=of model, anchor=center,label={[shift={(2mm,-1mm)}]-},label={[shift={(-3mm,-5.5mm)}]\tiny +}] (sum) {};
\node [coordinate, right=of sum] (error) {};
\node [block, dashed, fill=gray, anchor=center, text width=7cm, align=center] at ($(system)!.5!(model)$) {\textsc{Measurement}};
% Connect nodes
\draw [->, decorate, decoration={snake, post length=1mm}] (disturbances) -- node {\(d'\)} (system);
\draw [->] (input) -- node {\(u'\)} (system);
\draw [->] (system) -- node {\(t'\)} (output);
\draw [->] (model) -- node {\(y\)} (sum);
\draw [->] (sum) -- node {\(\epsilon\)} (error);
\draw [->] (infork) |- node [anchor=south west] {\(u\)} (model);
\draw [->] (outfork) -| (sum.north) node [very near end] {\(t\)};
\end{tikzpicture}
\end{document}
答案3
对于那些可能感兴趣的人,这里有一个解决方案MetaPost和元对象包,位于 LuaLaTeX 程序中。它基于s
和m
参数,允许分别以点(s,0)
和为中心定位“系统”和“模型”框(s, m)
。
\documentclass[border=2mm]{standalone}
\usepackage{luamplib}
\mplibtextextlabel{enable}
\begin{document}
\begin{mplibcode}
input metaobj
s := 4.5cm; m := -3cm; % locates upper and lower boxes
beginfig(1);
% Central box
newBox.msrmt("Measurement") "filled(true)", "fillcolor(.8white)",
"dx(.6s)", "framestyle(dashed evenly)";
msrmt.c = (s, .5m); drawObj(msrmt);
% Upper and lower boxes
newBox.syst("System") "dx(2mm)", "dy(3mm)";
newBox.model("Model") "dx(2mm)", "dy(3mm)";
syst.c = (s, 0); model.c = (s, m);
drawObj(syst); drawBox(model);
% Empty circle
ep := .5(xpart syst.w); t := xpart syst.e + ep; u := xpart syst.w - ep;
newCircle.circ("") "circmargin(1.5mm)";
circ.c = (t, m);
drawObj(circ);
% Connections
drawarrow origin -- syst.w;
drawarrow (u, 0) -- (u, m) -- model.w;
drawarrow syst.e -- (t+ep, 0);
drawarrow (t, 0) -- circ.n;
drawarrow model.e -- circ.w;
drawarrow circ.e -- (t+ep, m);
% The spring (and its label)
newEmptyBox.upper(0, 0); upper.c = (s, -.75m);
picture lab; lab = textext("$d'$");
nczigzag(upper)(syst) "coilwidth(2.5mm)", "coilarmA(0mm)",
"coilarmB(3mm)", "linearc(.4mm)", "labpic(lab)", "labdir(rt)";
% Other labels
label.top("$u'$", (u, 0)); label.urt("$u$", (u, m));
label.top("$t'$", (t, 0));
label.top("$y$", .5(model.e+circ.w));
label.rt("$t$", (t, ypart(.5(msrmt.s+circ.n))));
label.top("$\epsilon$", .5[(t,m), (t+ep, m)]);
labeloffset := .5bp;
label.llft("\tiny$+$", circ.sw);
label.urt("\tiny$-$", circ.ne);
labeloffset := 3bp;
endfig;
\end{mplibcode}
\end{document}
答案4
谢谢,我最终将 Ignasi 和 Alenanno 的答案混合在一起,如下所示:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows, positioning, patterns, calc, decorations.pathmorphing}
\begin{document}
\tikzstyle{block} = [draw, rectangle, inner sep=6pt, minimum width=2cm, minimum height=1cm, align=center]
\tikzstyle{joint} = [draw, circle, minimum size=1em, anchor=center]
\tikzstyle{layer} = [draw, rectangle, dashed, fill=gray!20, minimum width=7cm, minimum height=8mm, align=center, anchor=center]
\begin{tikzpicture}[>=stealth, auto, node distance=2cm]
% Place nodes
\node [block] (system) {System};
\node [block, below=of system] (model) {Model};
\node [layer] at ($(system)!.5!(model)$) {\textsc{Measurement}};
\coordinate [left=of system] (infork) {};
\coordinate [left=of infork] (input) {};
\coordinate [right=of system] (outfork) {};
\coordinate [right=of outfork] (output) {};
\coordinate [above=of system] (disturbances) {};
\node [joint, label={[inner sep=1pt]210:\tiny\(+\)}, label={[inner sep=1pt]60:\tiny\(-\)}] (sum) at (outfork|-model) {};
\coordinate (error) at (output|-model) {};
% Connect nodes
\draw [->, decorate, decoration={snake, post length=1mm}] (disturbances) -- node {\(d'\)} (system);
\draw [->] (input) -- node {\(u'\)} (system);
\draw [->] (system) -- node {\(t'\)} (output);
\draw [->] (model) -- node {\(y\)} (sum);
\draw [->] (sum) -- node {\(\epsilon\)} (error);
\draw [->] (infork) |- node [anchor=south west] {\(u\)} (model);
\draw [->] (outfork) -| (sum.north) node [very near end] {\(t\)};
\end{tikzpicture}
\end{document}
获得下图(忽略周围的框架):
\coordinate
我按照Ignasi 的建议使用\node [coordinate]
。我还使用了
|-
和,-|
以便更好地对齐,正如 Ignasi 所建议的那样。顺便说一句,这就是我最终不接受 Alenanno 的解决方案的原因,因为Measurements
块没有完全居中对齐,输出叉也不完全位于节点上方sum
。(不确定下图中边缘重叠是否可见)
使用角度参考来放置
+
和-
符号,但是像 Alenanno 那样稍微缩短了字体。对于
Measurements
块的定位,我遵循了 Alenanno 的方法。这部分是阻止我接受 Ignasi 解决方案的部分,因为我正在寻找一个Measurements
跨越垂直线的块,如上面的手工图片所示。破解了一点 Alenanno 的代码,我刚刚创建了一种新的块样式。此外,Alenanno 关于
very near end
和anchor=south west
选项的提示非常有用!(这是 Ignasi 的解决方案不是 100% 令人满意的另一个细节)。
再次感谢两位。我不确定该接受哪个答案,因为两个答案都很有帮助,但后来我决定将它们混合起来并提出我最终使用的解决方案,希望能够帮助其他人。