7

I am attempting to draw the figure shown in the picture below in Metapost, where it is important that the edge between the boxes starts at the middle of the bottom line of the "perfect" box, and ends at the middle of the top line of the "chordal" box. After using the boxit command to make a box with the desired text, I set its coordinates using .c. Then I want to draw the line between the boxes before I draw the boxes themselves, however, I am unable to reference .n, .s, or any coordinates besides .c of the box. After some headache I finally found a workaround to do what I want, but it appears like black magic to me why it does. Maybe the calls to bpath.perfect and bpath.chordal somehow generates the necessary information. Can someone enlighten me as to what is going on?

Desired picture

prologues := 3;
%outputtemplate := "%j-%c.mps";

input boxes;

beginfig(0);
    % Boxes
    boxit.perfect(btex perfect etex); perfect.c=(0,0);
    boxit.chordal(btex chordal etex); chordal.c=15right+30down;

    % Will crash: 
    draw perfect.s--chordal.n;
    drawboxed(perfect, chordal);
endfig;

beginfig(1);
    % Boxes
    boxit.perfect(btex perfect etex); perfect.c=(0,0);
    boxit.chordal(btex chordal etex); chordal.c=15right+30down;

    % Black magic. This is never actually drawn.
    path temp;
    temp = perfect.c--chordal.c cutbefore bpath.perfect cutafter bpath.chordal;

    % Works perfectly fine:
    draw perfect.s--chordal.n;
    drawboxed(perfect, chordal);
endfig;

The error message I receive when I compile is the following:

This is MetaPost, version 1.999 (TeX Live 2015) (kpathsea version 6.2.1)
(/usr/local/texlive/2015/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2015/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./mwe.mp
(/usr/local/texlive/2015/texmf-dist/metapost/base/boxes.mp)
>> -ypart perfect.nw
! Undefined y coordinate has been replaced by 0.
<to be read again> 
                   {
--->{
     curl1}..{curl1}
l.13     draw perfect.s--
                         chordal.n;
?
  • The problem is that you have to place the boxes before you can refer to the .s .n etc anchors. This placement is done automatically when you call drawboxed, so the anchors work after the first drawboxed (or drawunboxed). If you want to use the anchors before you draw the boxes you can call fixsize(..list of suffixes..) and fixpos(..list of suffixes..). If you look at the source of boxes.mp it shows you how. – Thruston Jun 17 '16 at 19:30
  • The reason your "black magic" works is because bpath also automatically calls fixsize and fixpos. – Thruston Jun 17 '16 at 19:31
6

With boxes.mp you need to call drawboxed or drawunboxed before you can use any of the anchor suffixes for the boxes you have defined.

The simplest way to avoid the crash is to draw the boxes before you draw the connection; in other words swap the order of your commands, like so:

drawboxed(perfect, chordal);
draw perfect.s--chordal.n;

Like this, your example compiles without error.

The anchors are not defined until the fixpos and fixsize macros are called. These are called automatically when you call drawboxed or drawunboxed.

If you want to use the anchors before you draw the boxes then you have to call fixpos and fixsize yourself. So in the OP case, you could do this:

fixsize(perfect, chordal);
fixpos(perfect, chordal);
draw perfect.s--chordal.n;
drawboxed(perfect, chordal);

to avoid the error in the first draw. But usually it's cleaner just to call drawboxed first.

The reason that the OP "black magic" works is because the bpath macro also calls fixpos and fixsize automatically.

For more details, browse the source of boxes.mp.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.