Locating and adapting code generating trees

TeXmac’s \tree macro is a really nice feature and I would like to adapt it to draw so-called phylogenetic trees (i.e. horizontally oriented trees with nodes connected only by combinations of horizontal and verticle lines) to make myself more familiar with TeXmac’s code.

I looked for a \tree macro inside the macro editor and could not find it.
Hints for where I could find it and how I could get started would be very helpful for me.

This means that it is defined in C++ code as far as I understand. This would mean you have to write an independent one using Scheme; to me it looks similar to commutative diagrams, which exist only in an elementary implementation. See Challenge: create support for commutative diagram, [Feature Request] A Better Tool for Drawing Commutative Diagrams and possibly other discussions.

The tree macro is a primitive of TeXmacs, i.e. its behaviour is defined in the C++ code. You might want to search for TREE in the code to see how it is implements. Essentially the typesetter will create “boxes” for all the arguments and then create a tree_box with those boxes as children (in concater_rep::typeset_tree source:src/Typeset/Concat/concat_math.cpp). The appearance of the tree is determined in the constructor tree_box_rep::tree_box_rep as follows:

tree_box_rep::tree_box_rep (path ip, array<box> bs, font fn2, pencil pen2):
  composite_box_rep (ip), fn (fn2), pen (pen2)
{
  SI sep   = fn->sep;
  SI hsep  = 2*fn->spc->def;
  SI vsep  = 4*fn->spc->def;
  SI line_w= fn->wline;

  int i, n= N(bs), cw, w= 0, h= MIN_SI, x, x_0, up;
  for (i=1; i<n; i++) w += bs[i]->w();
  for (i=1; i<n; i++) h  = max (h, max (bs[i]->y2, fn->y2) + sep);
  w += (n-2)*hsep;
  cw = w;
  x_0= 0; if (bs[0]->w()>w) { x_0= (bs[0]->w()-w)>>1; w= bs[0]->w(); }
  up= min (bs[0]->y1, fn->y1) - sep - vsep;

  insert (bs[0], (w>>1)- ((bs[0]->x1+bs[0]->x2)>>1), 0);
  for (x=x_0, i=1; i<n; i++) {
    SI x_i= x- bs[i]->x1;
    SI y_i= up- h;
    insert (bs[i], x_i, y_i);
    x += bs[i]->w()+ hsep;
  }

  pencil tpen= pen->set_width (line_w);
  for (x=x_0, i=1; i<n; i++) {
    SI x_i= x + (bs[i]->w()>>1);
    SI y_i= up + max (bs[i]->y2, fn->y2) + sep - h;
    SI bm = w>>1;
    SI bw = min (bs[0]->w(), cw>>1);
    SI bx = bm + ((2*i-n) * bw) / (2*n-2);
    SI by = min (bs[0]->y1, fn->y1) - sep;
    insert (line_box (decorate_middle (ip), bx, by, x_i, y_i, tpen), 0, 0);
    x += bs[i]->w()+ hsep;
  }

  position ();
  border= up+ (vsep>>1);
  finalize ();
}

It is not clear to me how to customise the behaviour. Probably you can have some environment variables which control the appearance and then use this to modify this procedure to have the appearance you like. HTH

3 Likes

Thanks, this was what I was looking for (although I was hoping a simple Scheme macro might do the job).