2

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;

Metapost Tree

For comparison, I'll include the same tree made with qtree:

\documentclass{standalone}

\usepackage{qtree}

\begin{document}
    \Tree [.VoiceP [.DP\\He ] [ [.Voice ] [.$v$P\\runs ] ] ]
\end{document}

QTree Tree

The METAPOST version gets 90% of the way there, but there are some problems with the way that metaobj trees are drawn:

  1. A node's branches are each drawn from a different point, instead of a common point at the center-bottom of the node.
  2. The branching angle and branch lengths are not consistent across the tree. Ideally, these would be the same so that the height of the node text wouldn't change the tree structure too much and node-less branches wouldn't be bent.
  3. I'm not sure how to center multi-line labels.

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).

3
  • pst-jtree is format independent, (at least plain TeX and LaTeX) although it depends on pstricks. And tikz-qtree.sty is a wrapper for tikz-qtree.tex. I've never used it with plain TeX but it might be possible as the code doesn't seem to use any LaTeX specific constructs, and tikz itself is format independent.
    – Alan Munn
    Commented Jul 23, 2020 at 22:31
  • pstricks doesn't work properly with LuaTeX and ConTeXt.
    – user220367
    Commented Jul 23, 2020 at 22:45
  • @Noone yes I’m aware of that.
    – Alan Munn
    Commented Jul 24, 2020 at 0:31

2 Answers 2

3

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

enter image description here

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.

1

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:

enter image description here

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
     \def\s#1{\vbox{\let\\\cr\halign{\hfil ##\hfil\cr #1\crcr}}}.  
     etex
    

    then you can do things like: label(btex \s{Above\\below} etex, origin);

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .