TeX - LaTeX Asked by hatsvi on August 29, 2021
I’m trying to find the best way to draw linguistics-style trees in a way which is as agnostic as possible to the variety of TeX which is used (LaTeX, ConTeXt, or plain ol’ TeX). Most of the ways to draw trees are, understandably, made for LaTeX (the qtree
variants and forest
), and aren’t easily adapted to ConTeXt or plain TeX.
My first thought was to use METAPOST to draw the trees and include the results as PDF or PS graphics, since this removes any dependency on TeX varieties. I found the metaobj
package for METAPOST which makes drawing trees easy-ish. For example, I have the following 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;
For comparison, I’ll include the same tree made with qtree
:
documentclass{standalone}
usepackage{qtree}
begin{document}
Tree [.VoiceP [.DPHe ] [ [.Voice ] [.$v$Pruns ] ] ]
end{document}
The METAPOST version gets 90% of the way there, but there are some problems with the way that metaobj
trees are drawn:
How can metaobj
/METAPOST be used to get the desired tree style? And, taking a step back from METAPOST, is this the best way to draw trees in this style in a way which is agnostic to the TeX variant used? I went with METAPOST since it produced diagrams which could easily be used in any flavor of TeX, it allows for the inclusion of TeX code in the drawing routine (for example, to switch fonts), and it produces high-quality graphics with support for lots of useful things (for example, drawing movement arrows using regular METAPOST arrows, colors, all the regular drawing capabilities, support for multiple figures in the same file, etc).
Disclaimer: It is not a solution in Metapost, but it could be useful.
As Alan Munn commented, TikZ/PGF is generic, so tikz-qtree
and should be portable to Plain TeX and ConTeXt. forest
is also based on TikZ/PGF, but it is tricky due to its LaTeX dependencies. The following is an example of tikz-qtree
in ConTeXt I'm not proud of, but it is a proof of concept.
usemodule[tikz]
unprotect
%Shamelessly taken from:
%https://wiki.contextgarden.net/LaTeX_Math_in_ConTeXt
let@@end=end
appendtoks
letend=@@end
to everystoptext
%This is really ad hoc.
%It will possibly break things when you try
%loading other packages better suited
%to LaTeX
defbegin#1{%
csname #1endcsname}
defend#1{%
csname end#1endcsname}
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
For some reason, a similar approach for Plain doesn't work for me and I didn't expected as I'm not a Plain user, but is feasible as you can see.
Answered by user220367 on August 29, 2021
Disclaimer: this is in Metapost but it's not really a proper answer to the question.
It is, of course, possible to draw anything nicely with Metapost, such as this version of your tree:
but as you can see below, I did not do that using a qtree
-like syntax. Whether you think this is "easy" is a matter of opinion, experience, number of trees you want to do, etc.
You could invest time in writing some MP that processed qtree
notation, or in patching metaobj
, or in writing macros for your own notation, or you could just draw trees one at a time, like this:
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.
On the specific issues you have with metaobj
:
I cannot see any simple way to get it to draw the lines as you want -- it is aiming at the centre of each node and cutting the lines at the bounding boxes, this will mean that the lines are usually at different angles. There does not seem to be any option available to make it draw lines at regular angles.
Centering multiline labels is a plain TeX issue, rather than a metaobj
problem. Each label goes in an hbox
as usual, so you could add a block like this near the top of your file
verbatimtex
defs#1{vbox{letcrhalign{hfil ##hfilcr #1crcr}}}.
etex
then you can do things like: label(btex s{Abovebelow} etex, origin);
Answered by Thruston on August 29, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP