With this module, you can compose collages in a more automatic way. Instead of shifting collages manually, this module figures out the dimensions of each part of your drawing and places them seamlessly next to each other, above each other or on top of each other. This is all possible by keeping track of the envelope or bounding box of each collage.
Collages are positioned relative to their internal origin. By default, a collage's internal origin lays in its exact center. By shifting a collage, we change its internal origin and the way it composes with other collages. Another method to change the origin is by using alignments.
All these ideas are based on the Diagrams library for Haskell and the Scalable Graphics library for Clean. You can regard this module as a simplified version of above libraries.
An envelope defines the bounding box of a collage. It is sometimes referred to as a span box. Envelopes can become quite complex when we calculate them in all possible directions. Here, we restrict ourselves to four directions: up, down, right and left.
The four different directions in which we can calculate an envelope.
Calculate the opposite direction.
Up <-> Down
Left <-> RightCalculates the width of a collage.
The width is equivalent to the envelopes in the left and right directions:
width collage == envelope Left collage + envelope Right collageCalculates the height of a collage.
The height is equivalent to the envelopes in the up and down directions:
height collage == envelope Up collage + envelope Down collageCollages can be composed in three ways:
A more advanced way of combining collages is by imposition: placing one collage on top of a background and forgetting about the dimensions of the foreground. All ways of combining are expressed used one basic placing function, which you can use in some extreme cases where you need to place a collage but not combine it with others.
Place a list of collages next to each other, such that their origins are along a horizontal line. The first element in the list will be on the left, the last on the right.
horizontal [a, b, c]
+–––+–––+–––+
|(a)| b | c |
+–––+–––+–––+The new origin will be the origin of the first element in the list.
hcat in Diagrams.Place a list of collages next to each other, such that their origins are along a vertical line. The first element in the list will be on the top, the last on the bottom.
vertical [a, b, c]
+–––+
|(a)|
+–––+
| b |
+–––+
| c |
+–––+The new origin will be the origin of the first element in the list.
vcat in Diagrams.Place a list of collages on top of each other, with their origin points stacked on the "out of page" axis.
The first collage in the list is on top.
This actually is the same as the group operation in the Collage module.
stack [a, b, c]
+–––+
|(a)|
+–––+(Yes, b and c are somewhere below a...)
Note: this is called concat in Diagrams.
Note: when we create an operator (<>) like
(<>) a b =
stack [ a, b ]then (<>) forms a monoid together with empty.
(<>) is called atop in Diagrams.
The new origin will be the origin of the first element in the list.
Impose a collage on a background.
The call
impose fore backstacks fore on back.
The envelope of fore will be "forgotten"
and back will be used to calculate the envelope of the resulting collage.
+–––––––––––+
|(b)+–––+ |
| | a | | <-- new envelope
| +–––+ |
+–––––––––––+Obviously, this also works with the background having a smaller envelope than the foreground.
The new origin will be the origin of the background.
Place a collage beside another one in the given direction and combine them into a new one.
Most of the time it is way nicer to use horizontal or vertical to express your layout,
but beside dir can come into hand as a curried function.
The new origin will be the origin of the first argument.
beside dir forms a monoid with empty for every dir.beside in Diagrams.Shift a collage in a direction to precisely that position where it would touch the first one, without composing them.
Use this to position a collage next to another collage without actually composing them.
juxtapose in Diagrams.What is placing collages without being able to space them accordingly? These two collages are invisible and only take up some space. (Or they even don't...)
Create an empty collage of given width and height.
This is useful for getting your spacing right and for making borders.
hspace =
spacer 10 0
horizontal <| List.intersperse hspace [a, b, c]
+–––+ +–––+ +–––+
| a | | b | | c |
+–––+ +–––+ +–––+A collage that takes up no space. Good for things that appear conditionally:
horizontal [ a, if showMore then b else empty ]
+–––+– – – – – –+
|(a)| maybe b? |
+–––+– – – – – –+Shift a collage such that the origin is on the given anchor.
Use this, for example, when you like to align some collages to the top:
[a, b, c]
|> List.map (align top)
|> horizontal
+–(X)–+––––X––––+–X–+
| a | b | c |
| +–––––––––+ |
+–––––+ | |
+–––+Anchors are created by the functions from the section below.
Stack a collage on top of a specified anchor of a host.
Makes placing objects on a collage a lot easier:
drawing
|> at bottom dot
|> at upperRight dot
+–––––––––0
| drawing |
+––––0––––+instead of:
stack
[ dot
, align upperRight <| stack
[ dot
, align bottom drawing
]
]This does not change the origin of collage.
Shift a collage such that the envelope in all directions is equal.
This is the same as aligning on the base anchor:
center collage == align base collageAnchors are technically just functions. You can use any function as an anchor as long as it takes a collage and returns a displacement relative to its internal origin.
+(X)+
| |
+–––+ +––(X)
| |
+–––+ +–––+
| (X)
+–––+ +–––+
| |
+––(X) +–––+
| |
+(X)+ +–––+
| |
(X)––+ +–––+
(X) |
+–––+ (X)––+
| |
+–––+ +–––+
|(X)|
+–––+These two functions can aid in discovering how collages are composed.
Draw a red dot at the local origin of the collage.
Draw a red dotted box around the collage representing the envelope.
We can imagine some possible extensions which could aid in designing composable drawings:
baseX, and baseY (horizontalBase and vertialBase)?centerX, and centerY too?
Calculate the envelope of a collage relative to its internal origin.
The figure below illustrates the four distances that can be calculated. We represent the origin with
(X). When calling, for example,envelope Up, we calculate the distance from(X)to the upper edge of the rectangle.The same holds for the other three directions.