I want to draw diagrams that look a bit like this. Mathematically, you could describe them as directed acyclic graphs with dangling arcs. They're somewhat reminiscent of route diagrams.
Desired output
Source here. There are four lines dangling in at the top of diagram, then four nodes that operate on these lines, and finally three lines dangling out of the bottom of the diagram. I know how to create this particular diagram in TikZ, but I want to make a package for creating them in general.
Desired input
It is important to me that:
- the user is required to specify as little as possible, so that it is easy to create and modify big diagrams, and that
- the diagram is composed in a row-by-row fashion.
This is the code I would like my user to type, in order to generate the picture above (I explain the code in the next subsection):
\begin{wickersondiagram}[%
initial lines={a/{pos=10}, b/{pos=30}, c/{pos=50}, d/{pos=70}}]
\step[left=0, right=40, text=decide,%
incoming lines={a,b},%
outgoing lines={e/{pos=10,label=yes}, f/{pos=30,label=no}}]
\\
\step[left=20, right=60,%
pale,%
incoming lines={f,c},%
outgoing lines={g/{pos=30},h/{pos=50}}]
\\
\step[left=0, right=40, text=join,%
incoming lines={e,g},%
outgoing lines={i/{pos=20}}]
\step[left=60, right=80,%
incoming lines={d},%
outgoing lines={j/{pos=70}}]
\\
\end{wickersondiagram}
By 'row-by-row', I mean that if I removed the last few rows from this code, I would still obtain a perfectly valid picture, and it would look just like the one above but with the lower portion missing.
Explanation of desired input
The user starts the diagram by specifying the horizontal placements of the initial lines
. Each line is assigned a name, here a
, b
, c
and d
. While constructing the diagram, my package should maintain an implicit 'state', containing the names of the lines and their placements. At this point in the construction, the state is
{a ↦ 10, b ↦ 30, c ↦ 50, d ↦ 70}.
Then the user creates a \step
. The horizontal position is specified with the left
and right
keys. There is optional text
on the step, which is 'decide' in this case. The incoming lines
are removed from the state, and the outgoing lines
are added to the state. At this point the state becomes:
{e ↦ 10, f ↦ 30, c ↦ 50, d ↦ 70}.
The point of maintaining the state is so lines that are not involved in a particular step are drawn in without the user having to keep specifying them. For instance, the package should implicitly draw the lines c
and d
to the right-hand side of the 'decide' step.
Occasionally two or more steps occur in parallel, as seen at the bottom of the picture above. I propose to deal with this in the syntax by using \\
to explicitly start a new 'row' of steps.
My approach so far
My approach so far has been to try to store the state in a series of macros, e.g.:
\def\state@line@a{10}
\def\state@line@b{30}
\def\state@line@c{50}
\def\state@line@d{70}
\def\state@line@e{10}
\def\state@line@f{30}
and then maintain a comma-separated list of those lines which are currently in the state, e.g.:
\def\activelines{e,f,c,d}
My previous two questions (here and here), have resulted from my trying to get this approach to work. In those questions, I have condensed my code down to minimal working examples to show the particular technical problem I was facing. I thank the answerers for addressing those problems so thoroughly and considerately. However, since the same people are answering my questions each time, I suspect it is probably better if I just cut to the chase and show what I'm really working on. I have still idealised my problem a bit, to make it easier to explain, but I hope to have preserved most of the technical challenges.
Extensions
I would like eventually to extend my diagrams to much more complicated ones than the example shown above. For instance:
I want my lines to have customisable thickness (so the elements of the 'state' should really be tuples rather than single integers).
I want to add a command to 'twist' two or more lines over each other, swapping their horizontal positions.
The user must currently specify a
left
andright
position for each step, but I want eventually to calculate these automatically from the positions of the incoming and outgoing lines.I want to add special 'compound' nodes that contain diagrams within them.
I want to add another type of line.
I want to add a command to take a snapshot of the current 'state', and a command to restore a previous 'state'.
Therefore, it is important to me that your solutions are robust and understandable enough so that I can fiddle with them a lot!
pgfgantt
? That's not the purpose of the package of course, but could be a valid solution/starting point.:-)
pgfgantt
(for the rather independent boxes) andtikz-cd
(for the connections which needs to be built in the background). — I wonder about the vertical lines though. In the example you specify a x value at which they start and end. It might be easier to first draw them to a specific y value and then draw filled boxes over it; especially considering other shapes thanrectangle
s. If you want to do this with other shapes, you will otherwise need theintersections
library to find at least a point on the border.