% language=us runpath=texruns:manuals/nodes

% author    : Alan Braslau
% copyright : ConTeXt Development Team
% license   : Creative Commons Attribution ShareAlike 4.0 International
% reference : pragma-ade.nl | contextgarden.net | texlive (related) distributions
% origin    : the ConTeXt distribution
%
% comment   : Because this manual is distributed with TeX distributions it comes with a rather
%             liberal license. We try to adapt these documents to upgrades in the (sub)systems
%             that they describe. Using parts of the content otherwise can therefore conflict
%             with existing functionality and we cannot be held responsible for that. Many of
%             the manuals contain characteristic graphics and personal notes or examples that
%             make no sense when used out-of-context.
%
% comment   : A prototype of the nodes module was presented at the ConTeXt 2016 user meeting
%             and the first release was presented at the 2017 meeting. The module is part of
%             the MetaFun code modules.
%
% comment   : This manual orginates in an article by Alan so anything wrong in here is Hans
%             fault as he converted it.
%
% comment   : It is also being published as an article in TugBoat.
%
% comment   : The cover images are from the NASA website.

%\enabletrackers[metapost.showlog]

\definemeasure [layout:margin] [\paperheight/20]

\setuplayout
  [topspace=\measure{layout:margin},
   bottomspace=\measure{layout:margin},
   backspace=\measure{layout:margin},
   header=0pt,
   footer=\measure{layout:margin},
   width=middle,
   height=middle]

\setupbodyfont
  [dejavu,11pt]

\setupwhitespace
  [big]

\setuphead
  [chapter]
  [style=\bfc,
   interaction=all]

\setuppagenumbering
  [alternative=doublesided,
   location=]

\setupfootertexts
  [\documentvariable{title}][\pagenumber]
  [\pagenumber][\documentvariable{title}]

\setuphead
  [section]
  [style=\bfb]

\setuphead
  [subsection]
  [style=\bfa]

\setuphead
  [subsubsection]
  [style=\bf,
   after=]

\setuplist
  [interaction=all]

\setupalign
  [verytolerant,stretch]

% \definesymbol [1] [$\cdot$]

% Dot rather than bullet ... Alan hates bullets! Hans hates too small dots.
% So, a dash is OK? ;-)

\setupitemize
  [symbol=2] % dash rather than bullet, I hate bullets!

\setupnote
  [footnote]
  [next={ },
   split=verystrict,
   scope=page]

\setupinteraction
  [state=start,
   option=bookmark,
   color=darkmagenta,
   contrastcolor=darkmagenta]

\setupinteractionscreen
  [option=bookmark]

\placebookmarks
  [title,subject]
  [title,subject]

\enabledirectives
  [references.bookmarks.preroll]

\kindofpagetextareas\plusone % partial page. HH: low level, no high level switch (yet)

\definetextbackground
  [aside]
  [location=paragraph,
   frame=off,
   leftoffset=1ex,
   rightoffset=1ex,
   topoffset=1ex,
   bottomoffset=1ex,
   background=color,
   backgroundcolor=lightgray]

\definedescription
  [description]
  [location=hanging,
   width=broad,
   before={\blank},
   after={\blank}]

\defineparagraphs
  [two]
  [n=2,
   offset=1ex,
   background=color,
   backgroundcolor=gray]

\defineframed
  [node]
  [offset=1pt,
   foregroundstyle=\tfa]

\defineframed
  [nodeGreen]
  [node]
  [foregroundcolor=darkgreen,
   foregroundstyle=italic]

\defineframed
  [nodeSmall]
  [node]
  [foregroundstyle=\tfx]

\startbuffer [bib]
    @ARTICLE{Krebs1946,
        author   = {Krebs, H. A.},
        title    = {Cyclic processes in living matter},
        journal  = {Enzymologia},
        year     = {1946},
        volume   = {12},
        pages    = {88--100}
        language = {english},
    }

    @ARTICLE{Bethe1939a,
        author    = {Bethe, H. A.},
        title     = {Energy Production in Stars},
        journal   = {Phys. Rev.},
        year      = {1939},
        volume    = {55},
        pages     = {103–103},
        month     = {Jan},
        doi       = {10.1103/PhysRev.55.103},
        issue     = {1},
        publisher = {American Physical Society},
        XXurl     = {http://link.aps.org/doi/10.1103/PhysRev.55.103}
        language  = {english},
    }

    @ARTICLE{Bethe1939b,
        author    = {Bethe, H. A.},
        title     = {Energy Production in Stars},
        journal   = {Phys. Rev.},
        year      = {1939},
        volume    = {55},
        pages     = {434–456},
        month     = {Mar},
        doi       = {10.1103/PhysRev.55.434},
        issue     = {5},
        publisher = {American Physical Society},
        XXurl     = {http://link.aps.org/doi/10.1103/PhysRev.55.434}
        language  = {english},
    }

    @BOOK{Lawvere2009,
        author    = {Lawvere, F. William and Schanuel, Stephen H.},
        title     = {Conceptual Mathematics}
        subtitle  = {A first introduction to categories},
        edition   = {2\high{nd}},
        publisher = {Cambridge University Press},
        address   = {Cambridge, UK},
        year      = {2009}
        language  = {english},
    }

    @ARTICLE{Braslau2018,
        title     = {ConTeXt nodes},
        subtitle  = {commutative diagrams and related graphics},
        author    = {Braslau, Alan and Hamid, Idris Samawi and Hagen, Hans},
        year      = {2018},
        journal   = {TUGboat},
        volume    = {39},
        number    = {1},
        ISSN      = {0896-3207},
        url       = {https://www.tug.org/TUGboat/Contents/contents39-1.html},
        language  = {english},
    }
\stopbuffer

\usebtxdefinitions [apa]
\setupbtxrendering [apa] [pagestate=start] % index cite pages in bibliography

\usebtxdataset  [bib.buffer]

% Say, MP math arrows rather than font arrows:

\useMPlibrary[mat]

\definemathstackers
   [mp]
   [alternative=mp]

\definemathextensible [mp] [leftarrow]          ["2190]
\definemathextensible [mp] [rightarrow]         ["2192]
\definemathextensible [mp] [leftrightarrow]     ["2194]
\definemathextensible [mp] [longleftrightarrow] ["27F7]
\definemathextensible [mp] [rightoverleftarrow] ["21C4]

\startMPinitializations
  ahlength  := EmWidth ;
  ahangle   := 30 ;
  ahvariant := 1 ; % dimpled curved
  ahdimple  := 4/5 ;

  node_loopback_yscale := .7 ;
\stopMPinitializations

% Only here do we use the special nodes:: instance

\defineframed
  [mynode]
  [node]
  [offset=1pt,
   foregroundcolor=white]

\startreusableMPgraphic{nodes::krebs}

   % The Bethe cycle for energy production in stars (1939), following
   % Krebs (1946)

   save p ; path p[] ;
   p1 := (for i=0 step 60 until 300: dir(90-i).. endfor cycle) scaled 2.75cm ;
   p0 := p1 scaled  .5 ;
   p2 := p1 scaled 1.5 ;

   draw node(p1,0,"\mynode{\chemical{^{12}C}}") ;
   draw node(p1,1,"\mynode{\chemical{^{13}N}}") ;
   draw node(p1,2,"\mynode{\chemical{^{13}C}}") ;
   draw node(p1,3,"\mynode{\chemical{^{14}N}}") ;
   draw node(p1,4,"\mynode{\chemical{^{15}O}}") ;
   draw node(p1,5,"\mynode{\chemical{^{15}N}}") ;

   drawarrow fromtopaths.urt (true,p1,0,p1,1,"\mynode{a}") withcolor white ;
   drawarrow fromtopaths.rt  (true,p1,1,p1,2,"\mynode{b}") withcolor white ;
   drawarrow fromtopaths.lrt (true,p1,2,p1,3,"\mynode{c}") withcolor white ;
   drawarrow fromtopaths.llft(true,p1,3,p1,4,"\mynode{d}") withcolor white ;
   drawarrow fromtopaths.lft (true,p1,4,p1,5,"\mynode{e}") withcolor white ;
   drawarrow fromtopaths.ulft(true,p1,5,p1,6,"\mynode{f}") withcolor white ;

   draw node(p0,0,"\mynode{\chemical{^1H}}") ;
   draw node(p0,2,"\mynode{\chemical{^1H}}") ;
   draw node(p0,3,"\mynode{\chemical{^1H}}") ;
   draw node(p0,5,"\mynode{\chemical{^1H}}") ;

   drawarrow fromtopaths(3/10,p0,0,p1,0.5) withcolor white ;
   drawarrow fromtopaths(3/10,p0,2,p1,2.5) withcolor white ;
   drawarrow fromtopaths(3/10,p0,3,p1,3.5) withcolor white ;
   drawarrow fromtopaths(3/10,p0,5,p1,5.5) withcolor white ;

   draw node     (p2,0,"\mynode{\chemical{^4He}}")                ;
   draw node     (p2,1,"\mynode{$γ$}")                            ;
   draw node.lrt (p2,2,"\mynode{$\mathrm{e}^+ + ν_\mathrm{e}$}")  ;
   draw node     (p2,3,"\mynode{$γ$}")                            ;
   draw node     (p2,4,"\mynode{$γ$}")                            ;
   draw node.ulft(p2,5,"\mynode{$\mathrm{e}^+ + ν_\mathrm{e}$}")  ;

   drawarrow fromtopaths(-1/10,p1,0.5,p2,1) withcolor white ;
   drawarrow fromtopaths(-1/10,p1,1.5,p2,2) withcolor white ;
   drawarrow fromtopaths(-1/10,p1,2.5,p2,3) withcolor white ;
   drawarrow fromtopaths(-1/10,p1,3.5,p2,4) withcolor white ;
   drawarrow fromtopaths(-1/10,p1,4.5,p2,5) withcolor white ;
   drawarrow fromtopaths(-1/10,p1,5.5,p2,0) withcolor white ;

\stopreusableMPgraphic

\startuseMPgraphic{CoverPage}

    StartPage ;

        % Alan wanted a sun in the background combined somehow with the energy
        % harvesting molecule so here we go. The images that are used come from
        % the NASA website and I used them as screen saver for a while. The
        % version that I generate uses a variant from the one on the user's
        % machine.

        draw textext("\externalfigure[\framedparameter{imagename}]")
            xsized PaperWidth ysized (PaperHeight+4cm)
            shifted center Page shifted (0,2cm);

        for i=1 upto 512 :
            draw (textext("\reuseMPgraphic{nodes::krebs}") scaled (1/5 randomized 1/5))
            shifted (center Page randomized (PaperWidth,PaperHeight)) ;
        endfor ;

        draw (textext.ulft("\word{\documentvariable{title}}") xsized (PaperWidth/2))
            shifted (lrcorner Page)
            shifted (-PaperWidth/10,2PaperWidth/10)
            withcolor white;

        draw (textext.ulft("\word{\documentvariable{author}}") xsized (PaperWidth/2))
            shifted (lrcorner Page)
            shifted (-PaperWidth/10,PaperWidth/10)
            withcolor white;

    StopPage ;

\stopuseMPgraphic

\startsetups document:start

    % We each have our preferred cover... ;-)

    \doifmodeelse {atpragma} {
        \startMPpage[imagename=nodes-sun-pia-03150]
            \includeMPgraphic{CoverPage}
        \stopMPpage
    } {
        \startMPpage[imagename=nodes-sun-pia-03149]
            \includeMPgraphic{CoverPage}
        \stopMPpage
    }

\stopsetups

\startsetups document:stop

\stopsetups

% And now, the document!

\startdocument
  [title=Nodes,
   author=Alan Braslau,
   copyright=\ConTeXt\ development team,
   version=1.0]

\startsubject [title=Introduction]

A draft version of this manual was published in \cite[journal] [Braslau2018].
\cite [Braslau2018]

\blank

The graphical representation of textual diagrams is a very useful tool in the
communication of ideas. In category and topos theory, for example, many key
concepts, formulas, and theorems are expressed by means of \emph {commutative
diagrams}; these involve objects and arrows between them. Certain concepts
discovered by category theory, such as \emph {natural transformations}, are
becoming useful in areas outside of mathematics and natural science, e.g., in
philosophy. To make category and topos methods usable by both specialists and
non|-|specialists, commutative diagrams are an indispensable tool.
\startfootnote
    For many examples of formal and informal commutative diagrams, see \cite
    [authoryears] [Lawvere2009].
\stopfootnote
The use of nodal diagrams is not limited to category theory, for they may
represent a flow diagram (of a process, for example), a chemical reaction
sequence or pathways, or that of phases and phase transitions, a hierarchical
structure (of anything), a timeline or sequence of events or dependencies, a tree
of descendance or ascendance, etc.

The basic units of a node|-|based diagram include \emph {node objects}, each
attached to some point (= the \emph {node}) in some spatial relationship. Note
that to a single node might be associated a set of objects. Given a node, it also
stands in a spatial relation to some other node. The spatial relationship between
the set of nodes of a diagram need not be in a regular network, although they
quite often are. Note that the spatial relationship between nodes is graphical
and may represent, e.g., a temporal or logical relationship, or a transformation
of one object into another or into others (one interesting example might be that
representing cell division or, mitosis).

Given a spatial relation between any two nodes, a node|-|based diagram often
includes some \emph {path segment} or segments (such as arrows or other curves)
between two given nodes that \emph {relates} them. Each path segment may be
augmented by some textual or graphical label.

A very simple example of a node diagram is shown in \in{Figure} [fig:AB].

\startbuffer
\startMPcode
  clearnodepath ;
  nodepath = (left -- right) scaled .75cm ;
  draw node(0,"A") ;
  draw node(1,"B") ;
  drawarrow fromto(0,0,1) ;
\stopMPcode
\stopbuffer

\startplacefigure [reference=fig:AB]
    \getbuffer
\stopplacefigure

\startplacefigure [reference=fig:ID,
                   location={right,+2*hang}]
\startMPcode
  clearnodepath ; nodepath = origin ;
  draw node(0,"$O$") ;
  drawarrow fromto.urt  (.75cm,0,0) ;
  setbounds currentpicture to boundingbox currentpicture
      enlarged (1.2cm,0) ;
\stopMPcode
\stopplacefigure

More precisely, a \emph {node} is a point of intersection or branching of paths,
often a point on a regular lattice. (The nodes of the above diagram are the two
endpoints of a straight line segment.) Sometimes, however, a node might be a
single point as in an \emph {identity map} of category theory, referring to
itself:
\startfootnote
    The standard arrowhead in \METAPOST\ is a simple triangle, whose length and
    angle can be adjusted. \METAFUN\ provides further options, allowing this
    arrowhead to be barbed or dimpled. In the present article, we use the
    settings: \type {ahlength := EmWidth ; ahangle := 30 ; ahvariant := 1 ;
    ahdimple := 4/5 ;} The loop|-|back arrow paths used here deviate from a
    circular segment, becoming ellipsoidal, through the value \type
    {node_loopback_yscale := .7 ;} These are all set, of course, between a \type
    {\startMPinitializations} … \type {\stopMPinitializations} pair.
\stopfootnote

In this article we discuss a new \METAPOST\ module designed for handling
node|-|based graphics as well as a derivative simple \CONTEXT\ interface. To
illustrate, the code producing \inlinebuffer\ {could} be, in \METAPOST\ and the
\CONTEXT\ interface respectively:

\starttwo
    \METAPOST
    \startTEX
        \startMPcode
          draw node(0,"A") ;
          draw node(1,"B") ;
          drawarrow fromto(0,1) ;
        \stopMPcode
    \stopTEX
\two
    \CONTEXT
    \startbuffer
      \startnodes [dx=1.5cm]
        \placenode [0,0] {A}
        \placenode [1,0] {B}
        \connectnodes [0,1]
                      [alternative=arrow]
      \stopnodes
    \stopbuffer
    \typebuffer [option=TEX]
\stoptwo

drawing an arrow from A to B (or from node 0 to node 1): \getbuffer

\startitemize[packed]
    \startitem
        The \METAPOST\ code shown above has been slightly simplified, as will be
        seen later.
    \stopitem
    \startitem
        The \CONTEXT\ interface as used here is limited and will be explained a
        little later.
    \stopitem
\stopitemize

For beginners or casual users of \CONTEXT\ |<|including those who might be
intimidated by \METAPOST\ syntax|>| the ability to construct simple diagrams by
means of standard \CONTEXT\ syntax is very helpful. For those who have tried the
\CONTEXT\ interface and/or want to draw more advanced diagrams, the \METAPOST\
module is much more powerful and flexible.

\stopsubject

\startsubject [title=\METAPOST]

\METAPOST\ is a vector|-|graphics language which calls upon \TeX\ to typeset text
(such as labels); in \CONTEXT, furthermore, \METAPOST\ is integrated natively
through the library MPlib as well as the macro package \METAFUN. The tight
integration of \CONTEXT\ and \METAPOST\ provides advantages over the use of
other, external graphics engines. These advantages include ease of maintaining
coherence of style, as well as extensive flexibility without bloat. \METAPOST\
has further advantages over most other graphics engines, including a very high
degree of precision as well as the possibility to solve certain types of
algebraic equations. This last feature is rarely used but should not be
overlooked.

It is quite natural in \METAPOST\ to locate our node objects along a path or on
differing paths. This is a much more powerful concept than merely locating a node
at some pair of coordinates, e.g., on a square or a rectangular lattice, for
example (as in a table). Furthermore, these paths may be in three dimensions (or
more); of course the printed page will only involve some projection onto two
dimensions. Nor are the nodes restricted to location on the points defining a
path: they may have, as index, any \emph {time} along a given path \type {p}
ranging from the first defining point ($t = 0$) up to the last point of that path
($t ≤ \mathtt {length(p)}$), the number of defining points of a path.
\startfootnote
    Note that the time of a cyclic path is taken modulo the length of the path,
    that is $t$ outside of the range $[\mathtt0,\mathtt{length(p)}]$ will return
    the first or the last point of an open path, but will \quotation {wrap} for a
    closed path.
\stopfootnote

Given a path \type {p}, nodes are defined (implicitly) as \type {picture}
elements: \type {picture p.pic[] ;} This is a pseudo|-|array where the square
brackets indicates a set of numerical tokens, as in \type {p.pic[0]} or \type
{p.pic[i]} (for \type {i=0}), but also \type {p.pic0}. This number need not be an
integer, and \type {p.pic[.5]} or \type {p.pic.5} (not to be confused with \type
{p.pic5}) are also valid. These picture elements are taken to be located relative
to the path \type {p}, with the index \type {t} corresponding to a time along the
path, as in \type {draw p.pic[t] shifted point t of p;} (although it is not
necessary to draw them in this way). This convention allows the nodes to be
oriented and offset with respect to the path in an arbitrary manner.

Note that a path can be defined, then nodes placed relative to this path. Or the
path may be declared but remain undefined, to be determined only after the nodes
are declared. In yet another possibility, the path may be adjusted as needed, as
a function of whatever nodes are to be occupied. This will be illustrated through
examples further down.

\stopsubject

\startsubject [title=A few simple examples]

\startplacefigure [location=right,reference=fig:square]
    \startMPcode
        path p ; p := fullsquare scaled 3cm ;
        draw p ;
        for i=0 upto length p:
            draw point i of p
            withcolor red
            withpen pencircle scaled 5pt ;
        endfor ;
        % this looks better in the figure placement:
        setbounds currentpicture to boundingbox currentpicture
            enlarged (.5cm,0) ;
    \stopMPcode
\stopplacefigure

Let's begin with illustration of a typical commutative diagram from category
theory. Although it may appear trivial, this example helps to introduce
\METAPOST\ syntax. At the same time, a large part of the idea behind this module
is to facilitate use of this system without having to learn much \METAPOST.

A path is drawn as well as the points defining the path.

%\flushsidefloats

\startTEX
\startMPcode
  path p ; p := fullsquare scaled 3cm ; draw p ;
  for i=0 upto length p:
    draw point i of p
    withcolor red
    withpen pencircle scaled 5pt ;
  endfor ;
\stopMPcode
\stopTEX

\startbuffer
\startMPcode
  clearnodepath ;
  nodepath = p ;
  draw node(0,"\node{$G(X)$}") ;
  draw node(1,"\node{$G(Y)$}") ;
  draw node(2,"\node{$F(Y)$}") ;
  draw node(3,"\node{$F(X)$}") ;
  drawarrow fromto.bot(0,0,1, "\nodeSmall{$G(f)$}") ;
  drawarrow fromto.top(0,3,2, "\nodeSmall{$F(f)$}") ;
  drawarrow fromto.rt (0,2,1, "\nodeSmall{$η_Y$}") ;
  drawarrow fromto.lft(0,3,0, "\nodeSmall{$η_X$}") ;
\stopMPcode
\stopbuffer

\startplacefigure [location={right,+1*hang},reference=fig:natural,
    title={Drawn using \METAPOST\ interface}]
    \getbuffer
\stopplacefigure

Given the named path \type {nodepath}, we can now define and draw nodes as well
as connections between them (see \in{Figure} [fig:natural]):

%\flushsidefloats

\typebuffer [option=TEX]

\startaside
In working with \METAPOST, it is good practice to reset or clear a variable using
the directive \type {save} for the \emph {suffix} (or variable name) \type
{nodepath} contained in the directive \type {clearnodepath} (defined as
\quotation {\type {save nodepath ; path nodepath}}). The macros used here rely on
the creation of certain internal variables and may not function correctly if the
variable structure is not cleared. Indeed, any node may contain a combination of
picture elements, added successively, so it is very important to \type {save} the
variable, making its use local, rather than global. This point is particularly
true with \CONTEXT, where a single MPlib instance is used and maintained over
multiple runs.

The \CONTEXT\ directives \type {\startMPcode} … \type {\stopMPcode} include
grouping (\METAPOST\ \type {begingroup ;}… \type {endgroup ;}) and the use of
\type {save} (in \type {clearnodepath}) will make the suffix \type {nodepath}
local to this code block. In the code for \in{Figures} [fig:square] and \in
[fig:natural], the path \type {p} itself is not declared local (through the use
of a \type {save}); it therefore remains available for other \METAPOST\ code
blocks. We cannot do this with the default suffix name \type {nodepath} without
undesired consequences.

The directive \type {clearnodepath} used in the example above, much like the
\METAPOST\ command \type {clearxy} clearing the \type {(x,y)} pair also known as
\type {z}, uses \type {save} to clear the default suffix \type {nodepath}.
\stopaside

Note that one should not confuse the \METAPOST\ function \type {node()} with the
\CONTEXT\ command \type {\node{}}, defined as follows:

\starttwo
  \startTEX
  \defineframed
    [node]
    [frame=off,
     offset=1pt]
  \stopTEX
\two
  \startTEX
  \defineframed
    [nodeSmall]
    [node]
    [foregroundstyle=small]
  \stopTEX
\stoptwo

\type {\node{}} places the text within a \CONTEXT\ frame (with the frame border
turned|-|off), whereas the \METAPOST\ function \type {node(i,"…")} sets and
returns a picture element associated with a point on path \type {nodepath}
indexed by its first argument. The second argument here is a string that gets
typeset by \TEX. (The use of \type {\node{}} adds an \type {offset}).

By default, the \METAPOST\ function \type {fromto()} returns a path segment going
between two points of the path \type {nodepath}. The first argument (\type {0} in
the example above) can be used as a displacement to skew the path away from a
straight line (by an amount in units of the straight path length). The last
argument is a string to be typeset and placed midpoint of the segment. The
{suffix} appended to the function name gives an offset around this halfway point.
This follows standard \METAPOST\ conventions.

It is important to draw or declare the nodes \emph {before} drawing the
connections, using \type {fromto()}, in order to be able to avoid overlapping
symbols, as one notices that the arrows drawn in the example above begin and end
on the border of the frame (or bounding box) surrounding the node text. This
would of course not be possible if the arrow were to be drawn before this text
was known.

As will be seen further on, one can actually specify the use of any defined path,
without restriction to the built|-|in name \type {nodepath} that is used by
default. Furthermore, a function \type {fromtopaths()} can be used to draw
segments connecting any two paths which may be distinct. This too will be
illustrated further on.

The \CONTEXT\ syntax for the current example looks like this:

\startbuffer
  \startnodes [dx=3cm,dy=3cm]
    \placenode [0,0] {\node{$G(X)$}}
    \placenode [1,0] {\node{$G(Y)$}}
    \placenode [1,1] {\node{$F(Y)$}}
    \placenode [0,1] {\node{$F(X)$}}
    \connectnodes [0,1] [alternative=arrow,
      label={\nodeSmall{$G(f)$}},position=bottom]
    \connectnodes [3,2] [alternative=arrow,
      label={\nodeSmall{$F(f)$}},position=top]
    \connectnodes [2,1] [alternative=arrow,
      label={\nodeSmall{$η_Y$}}, position=right]
    \connectnodes [3,0] [alternative=arrow,
      label={\nodeSmall{$η_X$}}, position=left]
  \stopnodes
\stopbuffer

\startplacefigure [location=right,reference=fig:ConTeXt,
    title={Drawn using \CONTEXT\ interface}]
  \getbuffer
\stopplacefigure

\typebuffer [option=TEX]

\startplacefigure [reference=fig:indices,
  location=right,
  title={Coordinates and indices.\footnote {For variety, a rectangular oblique
         lattice is drawn in \in{Figure} [fig:indices].}}
  ]
  \startframed [frame=off,width=.33\textwidth,align=flushright]
  \startnodes [dx=3cm,dy=2cm,rotation=60]
    \placenode [0,0] {\node{(0,0)}}
    \placenode [1,0] {\node{(1,0)}}
    \placenode [1,1] {\node{(1,1)}}
    \placenode [0,1] {\node{(0,1)}}
    \connectnodes [0,1] [alternative=arrow,
      label={\nodeSmall{$0\rightarrow1$}},position=bottom]
    \connectnodes [3,2] [alternative=arrow,
      label={\nodeSmall{$3\rightarrow2$}},position=top]
    \connectnodes [2,1] [alternative=arrow,
      label={\nodeSmall{$~2\rightarrow1$}}, position=right]
    \connectnodes [3,0] [alternative=arrow,
      label={\nodeSmall{$3\rightarrow0$}}, position=upperleft]
  \stopnodes
  \stopframed
\stopplacefigure

This follows the more classic (and limited) approach of placing nodes on the
coordinates of a regular lattice, here defined as a 3~cm square network.
\startfootnote
    The lattice can be square (\type {dx} $=$ \type {dy}), rectangular
    (\type {dx} ≠ \type {dy}), or oblique (through \type {rotation} ≠ 90).
\stopfootnote
The arguments are then $(x,y)$ coordinates of this lattice and the nodes are indexed
0, 1, 2, … in the order that they are drawn. These are used as reference indices
in the commands \type {\connectnodes} (rather than requiring two \emph {pairs} of
coordinates); see \in {Figure} [fig:indices]. This might seem a bit confusing at
first view, but it simplifies things in the end, really!

To avoid such confusion, in particular when drawing complicated diagrams
containing many nodes, the \CONTEXT\ interface allows the use of a \type
{reference} or tag, assigning a symbolic name to a numbered node. The example of
\in{Figure} [fig:ConTeXt] can be redrawn a little more verbosely as:

\startbuffer
  \startnodes [dx=3cm,dy=3cm]
    \placenode [0,0] [reference=GX] {\node{$G(X)$}}
    \placenode [1,0] [reference=GY] {\node{$G(Y)$}}
    \placenode [1,1] [reference=FY] {\node{$F(Y)$}}
    \placenode [0,1] [reference=FX] {\node{$F(X)$}}
    \connectnodes [GX,GY] [alternative=arrow,
      label={\nodeSmall{$G(f)$}},position=bottom]
    \connectnodes [FX,FY] [alternative=arrow,
      label={\nodeSmall{$F(f)$}},position=top]
    \connectnodes [FY,GY] [alternative=arrow,
      label={\nodeSmall{$η_Y$}}, position=right]
    \connectnodes [FX,GX] [alternative=arrow,
      label={\nodeSmall{$η_X$}}, position=left]
  \stopnodes
\stopbuffer

\typebuffer [option=TEX]

Notice that, like for all \CONTEXT\ macros, one never mixes a
comma|-|separated list of arguments (\type {[0,0]}) with a key=value list
(i.e. \type {[reference=GX]}). Symbolic references are very useful for longer,
more complicated diagrams; additionally, this easily allows modification such as
the addition of nodes without having to keep track of counting the order in
which they were drawn.

An identity map, as shown in \in {Figure} [fig:ID], earlier, and, below, in \in
{Figure} [fig:Me] is achieved by connecting a node to itself:

\startbuffer
\startnodes [dx=2cm,dy=1cm]
  \placenode [0,0]  {\node{Me}}
  \placenode [1,-1] {\node{You}}
  \connectnodes [0,0] [alternative=arrow,
    offset=.75cm,position=topright,
    label=myself]
  \connectnodes [1,1] [alternative=arrow,
    offset=.75cm,position=bottomright,
    label=yourself]
\stopnodes
\stopbuffer

\startplacefigure [reference=fig:Me,title=Identity maps,
                   location=right]
  \getbuffer
\stopplacefigure

\typebuffer [option=TEX]

The scale (diameter) of the circular loop|-|back is set by the keyword \type
{offset=} (normally used to curve or bow|-|away a path connecting nodes from the
straight|-|line segment between them), and the \type {position=} keyword sets its
orientation.

\startbuffer
\startMPcode
clearnodepath ;
nodepath = fullsquare scaled 2cm ;
save A ; A = 3 ; draw node(A,"\node{A}") ;
save B ; B = 2 ; draw node(B,"\node{B}") ;
save C ; C = 0 ; draw node(C,"\node{C}") ;
save D ; D = 1 ; draw node(D,"\node{D}") ;

drawarrow fromto(0,B,C) ;
drawarrow fromto(0,A,D) crossingunder fromto(0,B,C) ;
\stopMPcode
\stopbuffer

\startplacefigure [reference=fig:crossingunder,
                   location={right,+3*hang},
                   title=A$\rightarrow$D under B$\rightarrow$C]
  \startframed [frame=off,width=5cm,align=middle]
    \getbuffer
  \stopframed
\stopplacefigure

Let us now consider the following code which illustrates the \METAFUN\ operator
\type {crossingunder}
\startfootnote
    The operator \type {crossingunder} is of such general use that it has been
    added to the \METAFUN\ base.
\stopfootnote
(see \in {Figure}[fig:crossingunder]). The \type {nodepath} indices are put into
variables \type {A}, \type {B}, \type {C}, and \type {D}, thus simplifying the
code.

\typebuffer [option=TEX]

\startplacefigure [reference=fig:sincos,
                   location=right,
                   title={\type{crossingunder}}]
    \startMPcode
        save u ; u := 2cm ;
        save p ; path p[] ;
        n := 64 ;
        p2 := for i=0 upto n : if i>0 : .. fi (3u*(i/n), u*sind(720*(i/n))) endfor ;
        p3 := for i=0 upto n : if i>0 : .. fi (3u*(i/n), u*cosd(720*(i/n))) endfor ;
        p4 := point 0 of p2 -- point (length p2) of p2 shifted (left*.01u) ;

        draw p2 withcolor red ;
        begingroup ;
            interim crossingscale := 20 ;
            draw (p3 crossingunder p2) crossingunder p4 withcolor blue ;
        endgroup ;
        drawarrow (p4 crossingunder p2) ;
    \stopMPcode
\stopplacefigure

Another illustration of the \type {crossingunder} operator in use is shown in \in
{figure} [fig:sincos]. Because the diagrams are all defined and drawn in
\METAPOST, one can easily use the power of \METAPOST\ to extend a simple node
drawing with any kind of graphical decoration.

This brings up an important point that has limited the development of a
full|-|featured \CONTEXT\ module up to now. A pure \METAPOST\ interface affords
much more flexibility than can be conveniently reduced to a set of \TeX\ macros;
the \CONTEXT\ interface has been written to maintain only basic functionality.
\startfootnote
    One can use \type {\nodeMPcode{}} to inject arbitrary \METAPOST\ code within
    a \type {\startnode} … \type {\stopnode} pair, although in this example one
    is probably better off using the straight \METAPOST\ interface.
\stopfootnote

\stopsubject

\startsubject [title=Cyclic diagrams]

For a somewhat more complicated example, let us consider the representation of a
catalytic process such as that given by \cite [author] [Krebs1946]. \cite
[Krebs1946] The input is shown coming into the cycle from the center of a circle;
the products of the cycle are spun|-|off from the outside of the circle. We start
by defining a circular path where each point corresponds to a step in the cyclic
process. Our example will use six steps (see \in {Figure} [fig:circles]).

We also want to define a second circular path with the same number of points at
the interior of this first circle for the input, and a third circular path at the
exterior for the output.

The code is as follows:

\startbuffer
\startMPcode
  save p ; path p[] ;
  % define a fullcircle path with nodes at 60° (rather than 45°)
  p1 := (for i=0 step 60 until 300: dir(90-i) .. endfor cycle) scaled 2.5cm ;
  p0 := p1 scaled  .5 ;
  p2 := p1 scaled 1.5 ;

  for i=0 upto 2:
    draw p[i] ;
    label.bot("\bf p" & decimal i, point 0 of p[i]) ;
    for j=1 upto length p[i]:
      draw point j of p[i] withpen currentpen scaled 10 withcolor red ;
      if i=1:
        label.autoalign(angle point j of p[i]) (decimal j, point j of p[i])
                                                        withcolor red ;
      fi
    endfor
  endfor
\stopMPcode
\stopbuffer

\typebuffer [option=TEX]

\startplacefigure [reference=fig:circles,
  location=right,
  title={The paths that we will use for the anchoring of nodes.}]
  \getbuffer
\stopplacefigure

[\type {autoalign()} is a feature defined within \METAFUN.]

Nodes will then be drawn on each of these three circles and arrows will be used
to connect these various nodes, either on the same path or else between paths.

The \METAPOST\ function \type {fromto()} is used to give a path segment that
points from one node to another. It \emph {assumes} the path \type {nodepath},
and in fact calls the function \type {fromtopaths} that explicitly takes path
names as arguments. That is, \type {fromto (d, i, j, …)} is equivalent to \type
{fromtopaths (d, nodepath, i, nodepath, j, …)}.

As stated above, this segment can be a straight line or else a path that can be
bowed|-|away from this straight line by a transverse displacement given by the
function's first argument (given in units of the straight segment length). When
both nodes are located on a single, defined path, this segment can be made to lie
on or follow this path, such as one of the circular paths defined above. This
behavior is obtained by using any non|-|numeric value (such as \type {true}) in
place of the first argument. Of course, this cannot work if the two nodes are not
located on the same path.

The circular arc segments labeled \emph {\darkgreen a–f} are drawn on \in
{figure} [fig:Bethe] using the following:

\startTEX
drawarrow fromtopaths.urt (true,p1,0,p1,1,"\nodeGreen{a}") ;
\stopTEX

for example, where \type {\nodeGreen} is a frame that inherits from \type
{\node}, changing style and color:

\startTEX
\defineframed
  [nodeGreen]
  [node]
  [foregroundcolor=darkgreen,
   foregroundstyle=italic]
\stopTEX

The bowed|-|arrows feeding into the cyclic process and leading out to the
products, thus between different paths, from the path \type {p0} to the path
\type {p1} and from the path \type {p1} to the path \type {p2}, respectively, are
drawn using the deviations \type {+3/10} and \type {-1/10} (to and from
half|-|integer indices, thus mid|-|step, on path \type {p1}):

\startTEX
drawarrow fromtopaths( 3/10,p0,0,p1,0.5) withcolor .6white ;
drawarrow fromtopaths(-1/10,p1,0.5,p2,1) withcolor .6white ;
\stopTEX

\startplacefigure [reference=fig:Bethe,
  title={The \cite[author] [Bethe1939a] cycle for the energy production in stars
         \cite[alternative=year,left=(,right=)] [Bethe1939a+Bethe1939b] in a
         \cite[author] [Krebs1946] representation of a catalytic process
         \cite[alternative=year,left=(,right=)] [Krebs1946].}]
\startMPcode

  % differs slightly from \reuseMPgraphic{nodes::krebs}

  % The Bethe cycle for energy production in stars (1939), following Krebs (1946)

  save p ; path p[] ;
  p1 := (for i=0 step 60 until 300: dir(90-i).. endfor cycle) scaled 2.75cm ;
  p0 := p1 scaled  .5 ;
  p2 := p1 scaled 1.5 ;

  bboxmargin := 0pt ;

  draw node(p1,0,"\node{\chemical{^{12}C}}") ;
  draw node(p1,1,"\node{\chemical{^{13}N}}") ;
  draw node(p1,2,"\node{\chemical{^{13}C}}") ;
  draw node(p1,3,"\node{\chemical{^{14}N}}") ;
  draw node(p1,4,"\node{\chemical{^{15}O}}") ;
  draw node(p1,5,"\node{\chemical{^{15}N}}") ;

  drawarrow fromtopaths.urt (true,p1,0,p1,1,"\nodeGreen{a}") ;
  drawarrow fromtopaths.rt  (true,p1,1,p1,2,"\nodeGreen{b}") ;
  drawarrow fromtopaths.lrt (true,p1,2,p1,3,"\nodeGreen{c}") ;
  drawarrow fromtopaths.llft(true,p1,3,p1,4,"\nodeGreen{d}") ;
  drawarrow fromtopaths.lft (true,p1,4,p1,5,"\nodeGreen{e}") ;
  drawarrow fromtopaths.ulft(true,p1,5,p1,6,"\nodeGreen{f}") ;

  draw node(p0,0,"\node{\chemical{^1H}}") ;
  draw node(p0,2,"\node{\chemical{^1H}}") ;
  draw node(p0,3,"\node{\chemical{^1H}}") ;
  draw node(p0,5,"\node{\chemical{^1H}}") ;

  drawarrow fromtopaths(3/10,p0,0,p1,0.5) withcolor .6white ;
  drawarrow fromtopaths(3/10,p0,2,p1,2.5) withcolor .6white ;
  drawarrow fromtopaths(3/10,p0,3,p1,3.5) withcolor .6white ;
  drawarrow fromtopaths(3/10,p0,5,p1,5.5) withcolor .6white ;

  draw node     (p2,0,"\node{\chemical{^4He}}") ;
  draw node     (p2,1,"\node{$γ$}") ;
  draw node.lrt (p2,2,"\node{$\mathrm{e}^+ + ν_\mathrm{e}$}") ;
  draw node     (p2,3,"\node{$γ$}") ;
  draw node     (p2,4,"\node{$γ$}") ;
  draw node.ulft(p2,5,"\node{$\mathrm{e}^+ + ν_\mathrm{e}$}") ;

  drawarrow fromtopaths(-1/10,p1,0.5,p2,1) withcolor .6white ;
  drawarrow fromtopaths(-1/10,p1,1.5,p2,2) withcolor .6white ;
  drawarrow fromtopaths(-1/10,p1,2.5,p2,3) withcolor .6white ;
  drawarrow fromtopaths(-1/10,p1,3.5,p2,4) withcolor .6white ;
  drawarrow fromtopaths(-1/10,p1,4.5,p2,5) withcolor .6white ;
  drawarrow fromtopaths(-1/10,p1,5.5,p2,0) withcolor .6white ;

\stopMPcode
\stopplacefigure

\startsubsubject [title={A lesson in \METAPOST}]

An \quote {array} of paths is declared through \type {path p[] ;} it is not a
formal array, but rather a syntactic definition of a collection of path variables
\type {p0}, \type {p1}, … each of whose name is prefixed with the tag \quotation
{p} followed by any number, not necessarily an integer (e.g., \type {p3.14} is a
valid path name). The syntax allows enclosing this \quotation {index} within
square brackets, as in \type {p[0]} or, more typically, \type {p[i]}, where \type
{i} would be a numeric variable or the index of a loop. Note that the use of
brackets is required when using a negative index, as in \type {p[-1]} (for \type
{p-1} is interpreted as three tokens, representing a subtraction). Furthermore,
the variable \type {p} itself, would here be a numeric (by default), so \type
{p[p]} would be a valid syntactic construction! One could, additionally, declare
a set of variables \type {path p[][] ;} and so forth, defining also \type
{p[0][0]} (equivalently, \type {p0 0}) for example as a valid path, coexisting
with yet different from the path \type {p0}.

\METAPOST\ also admits variable names reminiscent of a structure: \type {picture
p.pic[] ;} for example is used internally in the \type {node} macros, but this
becomes \type {picture p[]pic[] ;} when using a path \quote {array} syntax. These
variable names are associated with the suffix \type {p} and become all undefined
by \type {save p ;}.

\stopsubsubject

\startsubsubject [title={Putting it together}]

What follows is simple example of a natural transformation, discovered and
articulated in the course of a philosophical research project (by Idris Samawi
Hamid). \in {Figure} [fig:NT] represents what is called the Croce Topos [named
after the Italian philosopher Benedetto Croce (1866–1952)]:

\startbuffer
\startMPcode
  save nodepath ;
  path nodepath ;
  nodepath = ((0,0) -- (1,0) -- (3,0) --
              (3,1) -- (1,1) -- (0,1) --
              cycle) scaled 4cm ;
  draw node(0,"\node{Practical}") ;
  draw node(1,"\node{Economic}") ;
  draw node(2,"\node{Moral}") ;
  draw node(3,"\node{Conceptual}") ;
  draw node(4,"\node{Aesthetic}") ;
  draw node(5,"\node{Theoretical}") ;

  drawarrow fromto.rt (.1,5,0,"\node{$γ$}") ;
  drawarrow fromto.lft(.1,0,5,"\node{$γ'$}") ;
  drawarrow fromto.rt (.1,4,1,"\node{$Fγ$}") ;
  drawarrow fromto.lft(.1,1,4,"\node{$Fγ'$}") ;
  drawarrow fromto.rt (.1,3,2,"\node{$Gγ$}") ;
  drawarrow fromto.lft(.1,2,3,"\node{$Gγ'$}") ;

  drawarrow fromto.top( 0,4,3,"\node{\it concretization$_1$}") ;
  drawarrow fromto.bot(.1,3,4,"\node{\it abstraction$_1$}")
      dashed evenly ;
  drawarrow fromto.top( 0,1,2,"\node{\it concretization$_2$}") ;
  drawarrow fromto.bot(.1,2,1,"\node{\it abstraction$_2$}")
      dashed evenly ;
\stopMPcode
\stopbuffer

% Let's forget that and rather use \startnodes...

\startbuffer
\startnodes [dx=4cm,dy=4cm,alternative=arrow]
  \placenode [0,0] {\node{Practical}}
  \placenode [1,0] {\node{Economic}}
  \placenode [3,0] {\node{Moral}}
  \placenode [3,1] {\node{Conceptual}}
  \placenode [1,1] {\node{Aesthetic}}
  \placenode [0,1] {\node{Theoretical}}

  \connectnodes [5,0] [offset=.1,position=right, label={\node{$γ$}}]
  \connectnodes [0,5] [offset=.1,position=left,  label={\node{$γ'$}}]
  \connectnodes [4,1] [offset=.1,position=right, label={\node{$Fγ$}}]
  \connectnodes [1,4] [offset=.1,position=left,  label={\node{$Fγ'$}}]
  \connectnodes [3,2] [offset=.1,position=right, label={\node{$Gγ$}}]
  \connectnodes [2,3] [offset=.1,position=left,  label={\node{$Gγ'$}}]

  \connectnodes [4,3] [position=top, label={\node{\it concretization$_1$}}]
  \connectnodes [3,4] [postition=bottom,offset=.1, option=dashed,
                                     label={\node{\it abstraction$_1$}}]
  \connectnodes [1,2] [position=top, label={\node{\it concretization$_2$}}]
  \connectnodes [2,1] [position=bottom,offset=.1, option=dashed,
                                     label={\node{\it abstraction$_2$}}]
\stopnodes
\stopbuffer

\startplacefigure [reference=fig:NT,
    title={A representation of the Croce Topos}]
    \getbuffer
\stopplacefigure

Here we use the \CONTEXT\ interface to the node package:

\typebuffer [option=TEX]

\stopsubsubject

\stopsubject

\startsubject [title=Tree diagrams]

The tree diagram shown in \in {Figure} [fig:DNA] is drawn using four paths, each
one defining a row or generation in the branching. The definition of the spacing
of nodes was crafted by hand and is somewhat arbitrary: 3.8, 1.7, and 1 for the
first, second and third generations. This might not be the best approach, but
this is how I was thinking when I first created this figure.

\startplacefigure [location=force,reference=fig:DNA]
\startMPcode
  % third example: A tree diagram

  save u ; u := 2.25cm ;
  save n ; n := 2 ; % n children per generation

  save p ; path p[] ;
  p0 := origin ;
  numeric d[] ; d1 := 3.8 ; d2 := 1.7 ; d3 := 1 ;
  for g=1 upto 3:
    p[g] :=
      for i=0 upto length(p[g-1]):
        for c=0 upto n-1:
          if (i+c)>0: -- fi
          ((point i of p[g-1]) shifted (d[g]*(c/(n-1)-.5)*u,-u))
        endfor
      endfor ;
  endfor

  draw node(p0,0,  "\node{DNA interactions with surfaces}") ;
  draw node(p1,0,  "\node{repulsive:}") ;
  draw node(p1,1,  "\node{attractive: adsorption}") ;
  draw node(p2,0,  "\node{confinement}") ;
  draw node(p2,1,  "\node[align=middle,location=high]{depletion,\\macromolecular\\crowding}") ;
  draw node(p2,2,  "\node{chemisorption}") ;
  draw node(p2,3,  "\node{physisorption}") ;
  draw node(p3,5.5,"\node{immobilized}") ;
  draw node(p3,7,  "\node{mobile}") ;

  drawarrow fromtopaths(0,p0,0,p1,0) ;
  drawarrow fromtopaths(0,p0,0,p1,1) ;

  drawarrow fromtopaths(0,p1,0,p2,0) ;
  drawarrow fromtopaths(0,p1,0,p2,1) ;
  drawarrow fromtopaths(0,p1,1,p2,2) ;
  drawarrow fromtopaths(0,p1,1,p2,3) ;

  drawarrow fromtopaths(0,p2,2,p3,5.5) ;
  drawarrow fromtopaths(0,p2,3,p3,5.5) ;
  drawarrow fromtopaths(0,p2,3,p3,7) ;

\stopMPcode
\stopplacefigure

Ultimately, one can do better by allowing \METAPOST\ to solve the relevant
equations and to determine this spacing automatically. Because it is a somewhat
advanced procedure, this approach will be first illustrated through a very simple
example of a diagram where the nodes will be placed on a declared but undefined
path:

\startTEX
save p ; % path p ;
\stopTEX

The \type {save p ;} assures that the path is undefined. This path will later be
defined based on the contents of the nodes and a desired relative placement. In
fact, it is not even necessary to declare that the suffix will be a path, as the
path will be declared and automatically built once the positions of all the nodes
are determined. To emphasize this point, the \type {path} declaration above is
commented|-|out.

\startdescription {Warning:}
Solving equations in \METAPOST\ can be non|-|trivial for those who are less
mathematically inclined. One needs to establish a coupled set of equations that
is solvable: that is, fully but not over|-|determined.
\stopdescription

A few helper functions have been defined: \type {makenode()} returns a suffix
(variable name) corresponding to the node's position. The first such node can be
placed at any finite point, for example the drawing's origin. The following nodes
can be placed in relation to this first node:

% \startframed [frame=off,align=text,offset=overlay] % keep this together on one page.
\startTEX
save nodepath ;
save first, second, third, fourth ;
pair first, second, third, fourth ;
first.i  = 0 ; first  = makenode(first.i, "\node{first}") ;
second.i = 1 ; second = makenode(second.i,"\node{second}") ;
third.i  = 2 ; third  = makenode(third.i, "\node{third}") ;
fourth.i = 3 ; fourth = makenode(fourth.i,"\node{fourth}") ;

first  = origin ;
second = first
       + betweennodes.urt(nodepath,first.i, nodepath,second.i,whatever) ;
third  = second
       + betweennodes.lft(nodepath,second.i,nodepath,third.i, whatever) ;
fourth = third
       + betweennodes.bot(nodepath,fourth.i,nodepath,first.i,3ahlength) ;
\stopTEX
% \stopframed

The helper function \type {betweennodes()} returns a vector pointing in a certain
direction, here following the standard \METAPOST\ suffixes: \type {urt}, \type
{lft}, and \type {bot}, that takes into account the bounding boxes of the
contents of each node, plus an (optional) additional distance (here given in
units of the arrow|-|head length, \type {ahlength}). Using the keyword \type
{whatever} tells \METAPOST\ to adjust this distance as necessary. The above set
of equations is incomplete as written, so a fifth and final relation needs to be
added; the fourth node is also to be located directly to the left of the very
first node:
\startfootnote
    Equivalently, we could declare that the first node located to the right of
    the fourth node: \type {first = fourth + betweennodes.rt (nodepath, first.i,
    nodepath, fourth.i, 3ahlength) ;}
\stopfootnote

\startTEX
fourth = first
       + betweennodes.lft(nodepath,fourth.i,nodepath,first.i,3ahlength) ;
\stopTEX

Note that the helper function \type {makenode()} can be used as many times as
needed; if given no content, only returning the node's position. Additional nodes
can be added to this diagram along with appropriate relational equations, keeping
in mind that the equations must, of course, be solvable. This last issue is the
one challenge that most users might face. The function \type {node()} that was
used previously and returning a picture element to be drawn itself calls the
function \type {makenode()}, used here. The nodes have not yet been drawn:

\startplacefigure [location=right,reference=fig:relative]
\startMPcode
  save nodepath ;
  save first, second, third, fourth ;
  pair first, second, third, fourth ;
  first.i  = 0 ; first  = makenode(first.i, "\node{first}") ;
  second.i = 1 ; second = makenode(second.i,"\node{second}") ;
  third.i  = 2 ; third  = makenode(third.i, "\node{third}") ;
  fourth.i = 3 ; fourth = makenode(fourth.i,"\node{fourth}") ;

  first  = origin ;
  second = first  + betweennodes.urt(nodepath,first.i, nodepath,second.i,whatever) ;
  third  = second + betweennodes.lft(nodepath,second.i,nodepath,third.i, whatever) ;
  fourth = third  + betweennodes.bot(nodepath,fourth.i,nodepath,first.i,3ahlength) ;
  fourth = first  + betweennodes.lft(nodepath,fourth.i,nodepath,first.i,3ahlength) ;

  for i = first.i, second.i, third.i, fourth.i :
    draw node(i) ;
    drawarrow fromto(0,i,i+1) ;
  endfor
\stopMPcode
\stopplacefigure

\startTEX
for i = first.i, second.i, third.i, fourth.i :
  draw node(i) ;
  drawarrow fromto(0,i,i+1) ;
endfor
\stopTEX

This results in \in {Figure} [fig:relative]. The path is now defined as one
running through the position of all of the defined nodes, and is cyclic.

Using this approach, that of defining but not drawing the nodes until a complete
set of equations defining their relative positions has been constructed, imposes
several limitations. First, the nodes are expected to be numbered from $0$ up to
$n$, continuously and without any gaps for each defined path. This is just an
implicit, heuristic convention of the path construction. Second, when finally
defining all the nodes and their positions, the path needs to be constructed. A
function, \type {makenodepath(p) ;} accomplishes this; it gets implicitly called
(once) upon the drawing of any \type {node()} or connecting \type {fromto}. Of
course, \type {makenodepath()} can always be called explicitly once the set of
equations determining the node positions is completely defined.

\startparagraph [style=bold]
We once again stress that the writing of a solvable yet not over|-|determined set
of equations can be a common source of error for many \METAPOST\ users.
\startfootnote
    The generous use of descriptive variables as we try to illustrate in the
    examples here can help tremendously in keeping track of multiple equations.
\stopfootnote
\stopparagraph

Another such example is the construction of a simple tree of descendance or
family tree. There are many ways to draw such a tree; in \in {figure}
[fig:descendance] we will show only three generations.

\startplacefigure [location=here,reference=fig:descendance,
  title={A tree of descendance}]
\startMPcode
  save p ; % path p[], p[][] ; get automagically defined
  save spacing ; spacing = 5pt ;
  save d ; d = 4ahlength ;

  save mother, father ; pair mother, father ;

  mother = makenode(p,0,"\node{mother}") ;
  father = makenode(p,1,"\node{father}") ;

  mother = origin ;
  father = mother + betweennodes.rt(p,0,p,1,spacing) ;

  % first generation
  save child, spouse ; pair child[], spouse[] ;
  child = 0 ; spouse = 1 ;

  child1  = makenode(p0,child, "\node{child1}") ;
  spouse1 = makenode(p0,spouse,"\node{spouse}") ;
  child2  = makenode(p1,child, "\node{child2}") ;
  spouse2 = makenode(p1,spouse,"\node{spouse}") ;

  .5[child1,child2] = mother + d*down ;
  spouse1 = child1  + betweennodes.rt(p0,child, p0,spouse,spacing) ;
  child2  = spouse1 + betweennodes.rt(p0,spouse,p1,child, whatever) ;
  spouse2 = child2  + betweennodes.rt(p1,child, p1,spouse,spacing) ;

  % second generation
  save grandchild, grandspouse ; pair grandchild[], grandspouse[] ;
  grandchild1  = makenode(p0 0,child, "\node{grandchild1}") ;
  grandspouse1 = makenode(p0 0,spouse,"\node{spouse}") ;
  grandchild2  = makenode(p0 1,child, "\node{grandchild2}") ;
  grandspouse2 = makenode(p0 1,spouse,"\node{spouse}") ;
  grandchild3  = makenode(p1 0,child, "\node{grandchild3}") ;
  grandspouse3 = makenode(p1 0,spouse,"\node{spouse}") ;
  grandchild4  = makenode(p1 1,child, "\node{grandchild4}") ;
  grandspouse4 = makenode(p1 1,spouse,"\node{spouse}") ;

  .5[grandchild1,grandchild2]  = child1 + d*down ;
  .5[grandchild3,grandchild4]  = child2 + d*down ;
  grandchild2  = grandchild1 + betweennodes.rt(p0 0,child,p0 1,child,spacing) ;
  grandchild3  = grandchild2 + betweennodes.rt(p0 1,child,p1 0,child,spacing) ;
  grandchild4  = grandchild3 + betweennodes.rt(p1 0,child,p1 1,child,spacing) ;
  grandspouse1 = grandchild1 + nodeboundingpoint.bot(p0 0,child)
                             + nodeboundingpoint.lrt(p0 0,spouse) ;
  grandspouse2 = grandchild2 + nodeboundingpoint.bot(p0 1,child)
                             + nodeboundingpoint.lrt(p0 1,spouse) ;
  grandspouse3 = grandchild3 + nodeboundingpoint.bot(p1 0,child)
                             + nodeboundingpoint.lrt(p1 0,spouse) ;
  grandspouse4 = grandchild4 + nodeboundingpoint.bot(p1 1,child)
                             + nodeboundingpoint.lrt(p1 1,spouse) ;

  draw node(p,0) ;
  draw node(p,1) withcolor blue ;

  for i=0,1 :
    draw node(p[i],child) ;
    drawarrow fromtopaths(0,p,0,p[i],child) ;
    draw node(p[i],spouse) withcolor blue ;
    for j=0,1 :
      draw node(p[i][j],child) ;
      draw node(p[i][j],spouse) withcolor blue ;
    endfor
    drawarrow fromtopaths(0,p[i],child,p[i][0],child) ;
    drawarrow fromtopaths(0,p[i],child,p[i][1],child) ;
  endfor
\stopMPcode
\stopplacefigure

We leave it as an exercise to the reader to come|-|up with the equations used to
determine this tree (one can look at source of this document, if necessary).

The requisite set of equations could be hidden from the user wishing to construct
simple, pre|-|defined types of diagrams. However, such cases would involve a loss
of generality and flexibility. Nevertheless, the \ConTeXt-Nodes module \emph
{could} be extended in the future to provide a few simple models. One might be a
branching tree structure, although even the above example (as drawn) does not
easily fit into a simple, general model.

\blank

A user on the \CONTEXT\ mailing list asked if it is possible to make structure
trees for English sentences with categorical grammar, an example of which is
shown in \in {Figure} [fig:grammar].

\startbuffer
\startMPcode
  save p ; path p[] ;
  save n ; n = 0 ;
  % rather than parsing a string, we can use "suffixes":
  forsuffixes $=People,from,the,country,can,become,quite,lonely :
    p[n] = makenode(p[n],0,"\node{\it" & (str $) & "}")
         = (n,0) ; % we work first with unit paths.
    n := n + 1 ;
  endfor
  save u ; u := MakeupWidth/n ; %(columns) TextWidth/n ;

  % build upward tree

  vardef makeparentnode(text t) =
    save i, xsum, xaverage, ymax ;
    i = xsum = 0 ;
    forsuffixes $ = t :
      clearxy ; z = point infinity of $ ;
      xsum := xsum + x ;
      if unknown ymax : ymax = y ; elseif y > ymax : ymax := y ; fi
      i := i + 1 ;
    endfor
    xaverage = xsum / i ;
    ymax := ymax + 1 ;
    forsuffixes $ = t :
      clearxy ;
      z = point infinity of $ ;
      $ := $ & z -- (x,ymax) if i>1 : -- (xaverage,ymax) fi ;
    endfor
  enddef ;

  makeparentnode(p2,p3) ;
  makeparentnode(p4,p5) ;
  makeparentnode(p6,p7) ;
  makeparentnode(p1,p2) ;
  makeparentnode(p0,p1) ;
  makeparentnode(p4,p6) ;
  makeparentnode(p0,p4) ;
  makeparentnode(p0) ;

  % the paths are all defined but need to be scaled.

  for i=0 upto n-1 :
    p[i] := p[i] xyscaled (u,.8u) ;
    draw node(p[i],0) ;
  endfor

  save followpath ; boolean followpath ; followpath = true ;

  draw fromtopaths(followpath,p0,0,p0,1,"\node{H:N}") ;
  draw fromtopaths(followpath,p1,0,p1,1,"\node{Rel:Prep}") ;
  draw fromtopaths(followpath,p2,0,p2,1,"\node{Dr:Dv}") ;
  draw fromtopaths(followpath,p3,0,p3,1,"\node{H:N}") ;
  draw fromtopaths(followpath,p4,0,p4,1,"\node{M:Aux}") ;
  draw fromtopaths(followpath,p5,0,p5,1,"\node{H:Mv}") ;
  draw fromtopaths(followpath,p6,0,p6,1,"\node{M:Adv}") ;
  draw fromtopaths(followpath,p7,0,p7,1,"\node{H:Adj}") ;

  draw fromtopaths(followpath,p1,1,p1,2) ;
  draw fromtopaths(followpath,p2,3,p2,4) ;
  draw fromtopaths(followpath,p1,2,p1,3,"\node{M:PP}") ;
  draw fromtopaths(followpath,p2,1,p2,2) ;
  draw fromtopaths(followpath,p3,1,p3,2) ;
  draw fromtopaths(followpath,p2,2,p2,3,"\node{Ax:NP}") ;
  draw fromtopaths(followpath,p4,1,p4,2) ;
  draw fromtopaths(followpath,p5,1,p5,2) ;
  draw fromtopaths(followpath,p4,2,p4,3,"\node{P:VP}") ;
  draw fromtopaths(followpath,p6,1,p6,2) ;
  draw fromtopaths(followpath,p7,1,p7,2) ;
  draw fromtopaths(followpath,p6,2,p6,3,"\node{PCs:AdjP}") ;
  draw fromtopaths(followpath,p0,1,p0,2) ;
  draw fromtopaths(followpath,p1,3,p1,4) ;
  draw fromtopaths(followpath,p0,2,p0,3,"\node{S:NP}") ;
  draw fromtopaths(followpath,p4,3,p4,4) ;
  draw fromtopaths(followpath,p6,3,p6,4) ;
  draw fromtopaths(followpath,p4,4,p4,5,"\node{Pred:PredP}") ;
  draw node(p0,4.5,"\node{Cl}") ;
  draw fromtopaths(followpath,p0,3,p0,4.5) ;
  draw fromtopaths(followpath,p4,5,p4,6) ;
\stopMPcode
\stopbuffer

\startplacefigure [reference=fig:grammar,
    title={A categorical grammer structure tree}]
    \getbuffer
\stopplacefigure

Here, I chose to define a series of parallel paths, one per word, with one path
terminating whenever it joins another path (or paths) at a common parent.
Naturally, labeling each branch of the tree structure requires a knowledge of the
tree structure. The code is not short, but hopefully it is mostly clear.

\typebuffer [option=TEX]

Note that diagrams such as those constructed here will each be significantly
different, making the writing of a general mechanism rather complex. For example,
one might need to construct a tree branching up rather than down, or to the right
(or left), or even following an arbitrary path, such as a random walk. These can
all be achieved individually in \METAPOST\ without too much difficulty.

\stopsubject

\startsubject [title=A 3D projection]

Although \METAPOST\ is a 2D drawing language, it can be easily extended to work
in 3D. Several attempts have been made in the past ranging from simple to
complicated. Here, we will take a simple approach.

The \METAPOST\ language includes a triplet variable type, used to handle \type
{rgb} colors (it also has a quadruplet type used for \type {cmyk} colors). We
will use this \type {triplet} type to hold 3D coordinates. There is a separate
\CONTEXT\ module, entitled \type {three}, which creates a new \METAPOST\ instance
(also named \type {three}), which loads a set of macros that can be used to
manipulate these triplet coordinates.

\usemodule [three]

\startTEX
\usemodule [three]

\startMPcode{three}
  % code here
\stopMPcode
\stopTEX

For our purposes here, only one function is really necessary: \type
{projection()} that maps a 3D coordinate to a 2D projection on the page. This
will not be a perspective projection having a viewpoint and a focus point, but
rather a very simple oblique projection, useful for, e.g., pseudo|-|3D schematic
drawings. The \type {Z} coordinate is taken to be \type {up} and the \type {Y}
coordinate taken to be \type {right}, both in the page of the paper. The third
coordinate \type {X} is an oblique projection in a right|-|hand coordinate
system.

\startbuffer
\startMPcode{three}
  save nodepath ;
  path nodepath ;
  nodepath = (projection Origin --
              projection (1,0,0) --
              projection (1,1,0) --
              projection (0,1,0) --
              projection (0,1,1) --
              projection (1,1,1) --
              projection (1,0,1) --
              projection (0,0,1) --
              cycle) scaled 5cm ;

  draw node(0,"\node{${\cal C}_{i\cal P}^{\mathrm{nt}}$}") ;
  draw node(1,"\node{${\cal C}_{i\cal G}^{\mathrm{nt}}$}") ;
  draw node(2,"\node{${\cal C}_{j\cal P}^{\mathrm{nt}}$}") ;
  draw node(3,"\node{${\cal C}_{j\cal G}^{\mathrm{nt}}$}") ;
  draw node(4,"\node{${\cal C}_{j\cal G}$}") ;
  draw node(5,"\node{${\cal C}_{j\cal P}$}") ;
  draw node(6,"\node{${\cal C}_{i\cal G}$}") ;
  draw node(7,"\node{${\cal C}_{i\cal P}$}") ;

  interim crossingscale := 30 ;
  drawdoublearrows fromto(0,0,1) ;
  drawdoublearrows fromto(0,1,2) ;
  drawdoublearrows fromto(0,2,3) ;
  drawdoublearrows fromto(0,3,0) crossingunder fromto(0,2,5) ;

  drawdoublearrows fromto(0,7,6) ;
  drawdoublearrows fromto(0,6,5) ;
  drawdoublearrows fromto.ulft(0,5,4,"\node{$τ_j$~}") ;
  drawdoublearrows fromto.top (0,7,4,"\node{$σ$}") ;

  drawdoublearrows fromto.lrt(0,0,7,"\node{$Ψ^{\mathrm{nt}}$}")
                                  crossingunder fromto(0,6,5) ;
  drawdoublearrows fromto(0,1,6) ;
  drawdoublearrows fromto(0,2,5) ;
  drawdoublearrows fromto(0,3,4) ;
\stopMPcode
\stopbuffer

\startplacefigure [location=right,
  reference=fig:cube]
  \getbuffer
\stopplacefigure

Intended for schematic drawings, there is no automatic hidden|-|line removal nor
effects like shading, and line crossings need to be handled manually (using \type
{crossingunder} introduced previously). In \in{Figure} [fig:cube] we draw a
simple cubical commutative diagram, with a node at each corner.

\typebuffer [option=TEX]

Note the use of \type {drawdoublearrows}, a new \METAFUN\ command that is
introduced here.

\stopsubject

\startsubject [title=Two final examples]

\startbuffer[mp:tikz-cd]
\startMPcode
  save nodepath ; save l ; l = 5ahlength ;
  save X, Y, Z, XxY, T ;
  pair X, Y, Z, XxY, T ;
  XxY.i = 0 ; XxY = makenode(XxY.i,"\node{$X\times_Z Y$}") ;
  X.i   = 1 ; X   = makenode(X.i,  "\node{$X$}") ;
  Z.i   = 2 ; Z   = makenode(Z.i,  "\node{$Z$}") ;
  Y.i   = 3 ; Y   = makenode(Y.i,  "\node{$Y$}") ;
  T.i   = 4 ; T   = makenode(T.i,  "\node{$T$}") ;
  XxY = origin ;
  X   = XxY + betweennodes.rt (nodepath,XxY.i,nodepath,X.i) + (l,0) ;
  Z   = X   + betweennodes.bot(nodepath,X.i,  nodepath,Z.i) + (0,-.8l);
  Y   = XxY + betweennodes.bot(nodepath,XxY.i,nodepath,Y.i) + (0,-.8l) ;
  T   = XxY + nodeboundingpoint.ulft(XxY.i)
            + nodeboundingpoint.lft (T.i) + l*dir(135) ;
  for i = XxY.i, X.i, Z.i, Y.i, T.i:
    draw node(i) ;
  endfor
  drawarrow fromto.top(0, XxY.i,X.i,  "\nodeSmall{$p$}") ;
  drawarrow fromto.rt (0,   X.i,Z.i,  "\nodeSmall{$f$}") ;
  drawarrow fromto.top(0,   Y.i,Z.i,  "\nodeSmall{$g$}") ;
  drawarrow fromto.rt (0, XxY.i,Y.i,  "\nodeSmall{$q$}") ;
  drawarrow fromto.top( .13,T.i,X.i,  "\nodeSmall{$x$}") ;
  drawarrow fromto.urt(-.13,T.i,Y.i,  "\nodeSmall{$y$}") ;
  drawarrow fromto    (0,   T.i,XxY.i,"\nodeSmall{$(x,y)$}")
      dashed withdots scaled .5
      withpen currentpen scaled 2 ;
\stopMPcode
\stopbuffer

% Rather, let's do it similarly to TikZ.

\startbuffer[mp:tikz-cd]
\startnodes [dx=2.5cm,dy=2cm,alternative=arrow]
  \placenode [0, 0] {\node{$X\times_Z Y$}}
  \placenode [1, 0] {\node{$X$}}
  \placenode [1,-1] {\node{$Z$}}
  \placenode [0,-1] {\node{$Y$}}
  \placenode [-1,1] {\node{$T$}}

  \connectnodes [0,1] [position=top,   label={\nodeSmall{$p$}}]
  \connectnodes [1,2] [position=right, label={\nodeSmall{$f$}}]
  \connectnodes [0,3] [position=right, label={\nodeSmall{$q$}}]
  \connectnodes [3,2] [position=top,   label={\nodeSmall{$g$}}]
  \connectnodes [4,0] [option=dotted,rulethickness=1pt,
                                       label={\nodeSmall{$(x,y)$}}]
  \connectnodes [4,1] [offset=+.13,position=top,
                                       label={\nodeSmall{$x$}}]
  \connectnodes [4,3] [offset=-.13,position=topright,
                                       label={\nodeSmall{$y$}}]
\stopnodes
\stopbuffer

\startplacefigure [reference=fig:tikz-cd,
                   location={right,+3*hang}]
    \getbuffer[mp:tikz-cd]
\stopplacefigure

We end this manual with two examples of more advanced commutative diagrams. The
following example, shown in \in {Figure} [fig:tikz-cd], illustrates what in
category theory is called a \emph {pullback}. It is inspired from an example
given in the TikZ CD (commutative diagrams) package.

The arrow labeled \quotation {$(x,y)$} is drawn \type {dashed withdots} and
illustrates how the line gets broken, implicitly \type {crossingunder} its
centered label.

\typebuffer[mp:tikz-cd] [option=TEX]

The previous diagram was drawn using the \CONTEXT\ interface. Our final example,
shown in \in {Figure} [fig:tikz-cd2], gives another \quotation {real|-|life}
example of a categorical pullback, also inspired by TikZ-CD, but this time drawn
through the \METAPOST\ interface and solving for positions.

\startbuffer[mp:tikz-cd2]
\startMPcode
  save nodepath ; save l ; l = 5ahlength ;
  save A, B, C, D, E ;
  pair A, B, C, D, E ;
  A.i = 0 ; A = makenode(A.i,"\node{$\pi_1(U_1\cap U_2)$}") ;
  B.i = 1 ; B = makenode(B.i,
  "\node{$\pi_1(U_1)\ast_{\pi_1(U_1\cap U_2)}\pi_1(U_2)$}") ;
  C.i = 2 ; C = makenode(C.i,"\node{$\pi_1(X)$}") ;
  D.i = 3 ; D = makenode(D.i,"\node{$\pi_1(U_2)$}") ;
  E.i = 4 ; E = makenode(E.i,"\node{$\pi_1(U_1)$}") ;
  A = origin ;
  B = A + betweennodes.rt(nodepath,A.i,nodepath,B.i) + (  l,0) ;
  C = B + betweennodes.rt(nodepath,B.i,nodepath,C.i) + (.7l,0) ;
  D = .5[A,B] + (0,-.9l) ;
  E = .5[A,B] + (0, .9l) ;

  for i = A.i, B.i, C.i, D.i, E.i :
      draw node(i) ;
  endfor
  drawarrow fromto.llft( 0,A.i,D.i,"\smallnode{$i_2$}") ;
  drawarrow fromto.ulft( 0,A.i,E.i,"\smallnode{$i_1$}") ;
  drawarrow fromto     ( 0,D.i,B.i) ;
  drawarrow fromto     ( 0,E.i,B.i) ;
  drawarrow fromto.urt( .1,E.i,C.i,"\smallnode{$j_1$}") ;
  drawarrow fromto.lrt(-.1,D.i,C.i,"\smallnode{$j_2$}") ;
  drawarrow fromto.top(  0,B.i,C.i) dashed evenly ;
  draw textext.top("{\tfxx\strut$\simeq$}")
      shifted point .4 of fromto(0,B.i,C.i) ;
\stopMPcode
\stopbuffer

\startplacefigure [location=here,reference=fig:tikz-cd2]
    \getbuffer[mp:tikz-cd2]
\stopplacefigure

\typebuffer[mp:tikz-cd2] [option=TEX]

\stopsubject

\startsubject [title=Conclusions]

There was initial consensus at the 2017 \CONTEXT\ Meeting in Maibach, Germany,
where a version of this package was presented, that there was little use of
developing a purely \CONTEXT\ interface. Rather, the \METAPOST\ package should be
sufficiently accessible. Since then, however, we decided that the development of
a derivative \CONTEXT\ interface implementing some basic functionality could
indeed be useful for many users, although it will necessarily remain somewhat
limited. Users are recommended to turn to the pure \METAPOST\ interface when more
sophisticated functionality is needed.

\stopsubject

\startsubject [title=Acknowledgements]

This module was inspired by a request made by Idris Samawi Hamid to draw a
natural transformation diagram (\in{Figure} [fig:natural]). The \METAPOST\ macros
that were developed then benefited from improvements suggested by Hans Hagen as
well as inspiration provided by Taco Hoekwater.

The cover artwork one can recognize as coming under the hand of Hans Hagen that
he produced when I mentioned that I wanted to do something along these lines. It
fits very well into the style of manual covers that we distribute with \CONTEXT.
This manual therefore has been co|-|written by Hans and Alan.

\stopsubject

\startsubject [title=References]

    \placelistofpublications

\stopsubject

\stoptitle

\stoptext
