Edge labels for Arrows?

Skip to first unread message


Nov 11, 2018, 10:33:20 AM11/11/18
to diagrams-discuss

I am quite new to diagrams and I would like to create finite state automata with it, as a replacement for TikZ. As far as I am aware there are no solutions for placing nodes easily along arrows, the FSM in one of the tutorials places the edge label in an ad-hoc fashion as regular nodes, but I would rather like to have something that works similar to TikZ - I don't want to think about the edge label positions in absolute terms. So I tried to patch up the Arrow module, extending it with edge labels that can be placed relative to the arrow and build an API around that.

My first approach was to patch connectPerim and connectOutside with named dummy diagrams at the calculated coordinates, calculate the position along the shaft and place some other diagram there. Then I saw that the placement is incorrect due to the head and tail and the required rescaling of the shaft. So the next thing I tried was extending ArrowOpts with an arrowLabel (which is an arbitrary diagram), and labelPos (between 0 and 1 along the shaft, 0 means at the tail, 1 at the head) and labelDist (distance in perpendicular direction from the shaft) and modifying the arrow' function accordingly. This approach does work more or less as I want, if the "base diagram" which gets the Arrows attached is not manipulated by scaling etc. after adding the edges.

In principle, this might be sufficient for my needs, but of course this is ugly and leaky, as one has to remember that everything falls apart when transforming the resulting diagram. So what I would like to achieve would be that rescaling the diagram afterwards also rescales the edge label nodes accordingly (and of course translations should also work as expected). So I started to digging into the rabbit hole with DelayedLeafs, but unfortunately I don't quite get it to work as I want. My approach was to make connectPerim/Outside variants that also create a delayed diagram and use information about "outer" transformations to adapt the diagrams stored in the arrowLabels accordingly, but I don't understand enough about the rendering process and how the whole structure is evaluated, etc. so I don't quite get it to behave correctly.

So my question is - should it be even possible to do what I want with the DelayedLeaf approach at all or am I wasting my time? Or is somebody already working on some nice solution for edge labels which I could rather use and contribute to? I attached the patched Arrow module, if somebody is interested.

Thanks and best regards,


Nov 18, 2018, 12:36:35 PM11/18/18
to diagrams-discuss

first of all to your question, yes, I think your approach should be able to acheive what you want but I'm not exactly sure what you need to do. The transform applied to the arrow is available to you (tr), I expect you need to incorporate is somehow. Also you trailPerc function seems to be doing something strange:

hsep 1 [stroke $ trailPerc i (circle 1) | i <- [0.1, 0.2 .. 1]]


As for what over people are doing, I've been working on a rewrite of diagrams and arrows are one of the things I've rewritten. Unfortunatly they're not very good state but you can look at https://github.com/cchalmers/diagrams/blob/master/src/Diagrams/Arrow.hs if you're curious. For the api I'd probably add a Located (Trail V2 Double) -> Measured (Diagram V2) function to the arrow options that lets you add labels given the trail used to draw the arrow (and a function that lets you easily add a label to trail)

I'm hoping that I've have my rewrite in a state where other people can easily start using it in the next couple of months. I'll make a post to this board once I've got it to that point.


Anton Pirogov

Nov 24, 2018, 2:21:42 PM11/24/18
to diagrams...@googlegroups.com

thanks for the response! Ok, trailPrec really works weirdly on this example, I didn't notice that while playing with arcs. But I wasn't aware that splitAtParam also works on Trails directly, so trailPerc did a lot of unnecessary work anyway. Now I have something working fine on your example. I agree that Located (Trail V2 Double) -> Measured (Diagram V2) looks like the right thing to add to the ArrowOpts, but then I first need to understand Located and Measured properly.

For now, I think I managed to make it work as I wanted with labelPos and labelDist, using the transformation given to the arrow, as you said (new version attached). The problem I encountered was that tr also translated the label diagram, so I centered it back and placed on the correct spot. But then effects of e.g. alignT on the original diagram are nullified. The solution I came up with is to extract the effect of such translations separately, and then re-apply it after transforming, by putting a "mark" onto the origin, centering and looking where the mark moved to obtain the translation vector. It is probably overly complicated, but seems to work fine.
2018-11-24-200730_424x289_scrot.png                 test.png

One weird behaviour I encountered is - when switching between PGF and Rasterific backend, the labels "swap" the side of the arrow they're located at, I suspect for some reason I get a different perpendicular vector, but the documentation of linear promises that I always get the "counter-clockwise perpendicular vector", Currenly I have to manually negate the labelDist to get the label where it's supposed to be. I don't see why the backend can affect this. I just mention it just in case this might be a bug (or maybe I just don't understand something). The behaviour can be seen using test.hs (compiling with Rasterific vs. inlining the Code in a diagram block in TeX).

Looking forward to the rewrite!


You received this message because you are subscribed to the Google Groups "diagrams-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to diagrams-discu...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Brent Yorgey

Feb 9, 2019, 10:14:38 PM2/9/19
to Anton Pirogov, diagrams-discuss
I know it has been a very long time since you sent this, but I had filed it away to respond to and never got around to it until now!  Anyway, re: the labels swapping sides when switching backends, I strongly suspect this has to do with the fact that some backends have a flipped Y-axis (i.e. the positive Y-axis points down) and some do not.  Diagrams handles this for you by applying an appropriate reflection transformation before sending a diagram to the backend to be rendered.  Off the top of my head I don't know how this would cause a label to end up on the opposite side of an arrow, but this is the only thing that could plausibly cause this kind of difference between backends.  You are certainly not getting a different output from perp --- the behavior of perp cannot possibly depend on which backend is chosen.

Reply all
Reply to author
0 new messages