using Names

11 views
Skip to first unread message

John Lato

unread,
May 14, 2013, 9:29:13 AM5/14/13
to diagrams...@googlegroups.com
Hello,

I have a project for which I'd like to do something like the following:

> myDiag = (square 1 # named "square") `atop` (circle 1 # named "circle")

and later, be able to apply attributes to the named components directly, something like

> modifySubdiag "square" (lc blue) myDiag

to set the line color of the named subdiagram.

Is there a good way to do this currently?  withName is close, but it doesn't actually replace the subdiagram within the full.  I could modify the subdiagram and place it atop, but that seems fairly wasteful (and possibly unreliable).

Is there a function I'm missing, or possibly an alternate approach I could take?

Thanks,
John L.

Brent Yorgey

unread,
May 14, 2013, 1:23:51 PM5/14/13
to diagrams...@googlegroups.com
Yeah, currently there is no functionality to let you modify a
subdiagram, although I have certainly considered it before. It's
tricky. Off the top of my head I do not know/remember whether it is
"major redesign"- tricky or just "someone needs to sit down and think
hard for a bit and bang out the code"-tricky. The problem is that
name maps are represented as just a finite map from names to
subdiagrams---in particular the information about where a subdiagram
sits within the tree corresponding to its parent diagram is not
stored, so there is no way to rebuild a parent diagram with a modified
subdiagram. Hmm, I suppose that along with each subdiagram we could store the
path from the root to the subdiagram. That might make a nice project
for someone.

OK, I created https://github.com/diagrams/diagrams-core/issues/39 for this.

In the meantime, one potential (though not all that nice) workaround
is to work with things of type

Map String Diagram

instead of directly with Diagrams. This means you essentially have to
manage the names yourself. However, because of various instances for
Maps (HasOrigin, Juxtaposable, Enveloped, ...) these should behave in
many ways just like the diagram you get when you mconcat all the
diagram values stored in the map. Obviously it is easy to modify
individual values stored in the map, and you can apply (mconcat
. elems) at the very end.

http://projects.haskell.org/diagrams/manual/diagrams-manual.html#delayed-composition
describes a similar trick, using lists instead of Map.

-Brent

John Lato

unread,
May 14, 2013, 11:02:44 PM5/14/13
to diagrams...@googlegroups.com
Thanks for this explanation; I had assumed it was possible and I just would need to write that function myself.  I think it's just "think hard and bang out code" tricky, but it also might lead to diagrams not working as expected.  Consider this case:

 - create a diagram with two named Subdiagrams
 - draw a line between the subdiagrams using the name/connection technique
 - translate one of the subdiagrams

Now the connecting line would go to the old position, leaving the subdiagram free.

Generally, any time a user performed some calculation that depended on the current envelope/trace/etc., modifying a subdiagram's envelope/trace/etc. wouldn't update that calculation.

For my use case of just applying colors this isn't a problem, but it sort of feels like opening up a can of worms.  So I guess as a design decision, does this seem like desirable behavior?  Would it be confusing for users?  The alternate behavior, with changes to a subdiagram back-propagating, seems to be much more complicated and maybe not even desirable.

From an implementation standpoint, the map to each sub-diagram would need to be modified every time the tree is modified.  This seems like a lot of extra book-keeping.  Maybe there's a way to change the Submap a bit so it's structured like a prefix tree, handling that automatically.

I don't know much about how diagrams are represented internally, but I also don't see a likely way to rebuild the spine of the tree.  The DUALTree docs suggest that if you need access to u/d values you have to replicate them yourself, and there doesn't seem to be much support for that.  If there were sufficient derivings to support SYB/Generics, one could at least replace all the leaf/leafU values with (Annot u (leaf)), but I think adding those derivings would also enable breaking the cached u values at the nodes, and we probably don't want that.  Oh well.

It should be easy enough to create a zipper over a DUALTree, which would be perfect for this sort of manipulation.  Would you be interested in having a module like that added to DUALTree?  Otherwise the same technique could be applied implicitly in a special-purpose function in diagrams-core.

Reply all
Reply to author
Forward
0 new messages