我正在尝试找到绘制语言学风格树的最佳方法,这种方法尽可能不受所用 TeX 种类的影响(LaTeX、ConTeXt 或普通 TeX)。可以理解的是,大多数绘制树的方法都是为 LaTeX(变体qtree
和forest
)设计的,并且不容易适应 ConTeXt 或普通 TeX。
我的第一个想法是使用 METAPOST 绘制树木并将结果作为 PDF 或 PS 图形包含在内,因为这样可以消除对 TeX 变体的任何依赖。我发现metaobj
METAPOST 包使绘制树木变得容易。例如,我有以下 MWE:
input metaobj;
prologues:=3;
beginfig(1);
setObjectDefaultOption("Tree")("hbsep")(5mm);
setObjectDefaultOption("Tree")("treenodehsize")(2cm);
setCurveDefaultOption("arrows")("draw");
t:=_T(Tr_(btex VoiceP etex))
(
Tr_(btex \vbox{\hbox{DP}\hbox{He}} etex),
_T(Tr_(""))
(
Tr_(btex Voice etex),
Tr_(btex \vbox{\hbox{$v$P}\hbox{runs}} etex)
)
);
Obj(t).c=origin;
draw_Obj(t);
endfig;
为了进行比较,我将包括用以下方法制作的同一棵树qtree
:
\documentclass{standalone}
\usepackage{qtree}
\begin{document}
\Tree [.VoiceP [.DP\\He ] [ [.Voice ] [.$v$P\\runs ] ] ]
\end{document}
METAPOST 版本已实现 90% 的功能,但在metaobj
绘制树的方式上存在一些问题:
- 每个节点的分支都是从不同的点绘制的,而不是从节点中心底部的公共点绘制的。
- 整个树的分支角度和分支长度并不一致。理想情况下,它们应该是相同的,这样节点文本的高度就不会过多地改变树结构,无节点的分支也不会弯曲。
- 我不确定如何使多行标签居中。
如何metaobj
使用 /METAPOST 来获得所需的树样式?退一步说,从 METAPOST 来看,这是以这种风格绘制树的最佳方式吗?这种方式与所用的 TeX 变体无关。我选择 METAPOST,因为它生成的图表可以轻松用于任何类型的 TeX,它允许在绘图例程中包含 TeX 代码(例如,切换字体),并且它可以生成高质量的图形,支持许多有用的东西(例如,使用常规 METAPOST 箭头绘制移动箭头、颜色、所有常规绘图功能、支持同一文件中的多个图形等)。
答案1
免责声明:这不是 Metapost 中的解决方案,但它可能有用。
正如 Alan Munn 所评论的,TikZ/PGF 是通用的,因此tikz-qtree
应该可以移植到 Plain TeX 和 ConTeXt。forest
也是基于 TikZ/PGF,但由于其对 LaTeX 的依赖,因此很棘手。以下是tikz-qtree
ConTeXt 中的一个例子,我并不为此感到自豪,但它是一个概念证明。
\usemodule[tikz]
\unprotect
%Shamelessly taken from:
%https://wiki.contextgarden.net/LaTeX_Math_in_ConTeXt
\let\@@end=\end
\appendtoks
\let\end=\@@end
\to \everystoptext
%This is really ad hoc.
%It will possibly break things when you try
%loading other packages better suited
%to LaTeX
\def\begin#1{%
\csname #1\endcsname}
\def\end#1{%
\csname end#1\endcsname}
\input pgfsubpic.tex
\input pgftree.tex
\input tikz-qtree.tex
\protect
\starttext
\starttikzpicture
[level distance=40pt]
\Tree [.S [.NP [.N this ] ]
[.VP [.V is ]
[.NP \edge[roof]; {a noun phrase} ] ] ]
\stoptikzpicture
\stoptext
由于某种原因,类似的 Plain 方法对我来说不起作用,而且我也没有想到,因为我不是 Plain 用户,但正如您所见,这是可行的。
答案2
免责声明:此是在 Metapost 中,但这实际上并不是该问题的正确答案。
当然,也可以画出任何事物与 Metapost 配合得很好,比如你的树的这个版本:
但正如您在下面看到的,我并没有使用qtree
-like 语法来做到这一点。您是否认为这“简单”取决于您的观点、经验、您想要做的树的数量等。
您可以花时间编写一些处理qtree
符号的 MP,或者进行修补metaobj
,或者为您自己的符号编写宏,或者您可以一次画一棵树,如下所示:
prologues := 3;
outputtemplate := "%j%c.eps";
beginfig(1);
numeric dx, dy;
dx = 34; dy = -13;
z0 = origin;
z1 = z0 + (-dx, dy);
z2 = z0 + (+dx, dy);
z21 = z2 + 3/4(-dx, dy);
z22 = z2 + 3/4(+dx, dy);
z100 = (x1, 3dy);
z200 = (x22, 3dy);
draw z1 -- z0 -- z2;
draw z21 -- z2 -- z22;
label.top(btex VoiceP etex, z0);
picture p[];
p1 = thelabel.bot(btex DP etex, z1);
p21 = thelabel.bot(btex Voice etex, z21);
p22 = thelabel.bot(btex {\it v\/}P etex, z22);
p100 = thelabel.bot(btex \strut He etex, z100);
p200 = thelabel.bot(btex \strut runs etex, z200);
forsuffixes $=1, 21, 22:
draw p$;
endfor
forsuffixes $=100, 200:
draw p$ withcolor 2/3 blue;
endfor
vardef connect(suffix a, b) =
draw point 1/2 of bbox p.a -- point 5/2 of bbox p.b dashed withdots scaled 1/4;
enddef;
connect(1, 100);
connect(22, 200);
undraw bbox currentpicture; % add a small margin
endfig;
end.
关于您遇到的具体问题metaobj
:
我看不出有什么简单的方法可以让它按照你想要的方式绘制线条——它瞄准每个节点的中心并在边界框处切割线条,这意味着线条通常处于不同的角度。似乎没有任何选项可以让它以规则的角度绘制线条。
多行标签居中是一个简单的 TeX 问题,而不是一个
metaobj
问题。每个标签都像往常一样放在一个位置\hbox
,因此您可以在文件顶部附近添加一个这样的块verbatimtex \def\s#1{\vbox{\let\\\cr\halign{\hfil ##\hfil\cr #1\crcr}}}. etex
然后你可以做类似的事情:
label(btex \s{Above\\below} etex, origin);