Lets start with the simplest example: drawing a straight line between two points. First the metapost code
draw (0,0)--(100,100) withpen pencircle scaled 4bp withcolor red;
Now the same code in Haskell (this needs to be wrapped around in a function and rendered to a png or pdf, but I’ll leave that part out).
lineColor red . lineWidth 4 . straight $ pathFromVectors [(0,0),(100,-100)]
I like the Metapost style better (since I have been using that for ages). One minor annoyance with diagrams is that positive values of y goes downwards rather than upwards. But the main trouble for me is prefix versus infix style. For diagrams, I find the infix style much easier to read. In this post, I will try to persuade Haskell to follow that style. The transforms in the diagram package have the signature
Something -> Diagram -> Diagram, while I want
Diagram -> Something -> Diagram. That is easy to fix
linecolor = flip lineColor linewidth = flip lineWidth fillcolor = flip fillColor
Now we can use
straight (pathFromVectors [(0,0),(100,-100)]) `linewidth` 4 `linecolor` red
Now lets try the next simplest example: drawing a circle. Again, the metapost code first
fill fullcircle scaled 100 withcolor 0.5green ; draw fullcircle scaled 100 withpen pencircle scaled 3 withcolor 0.5blue ;
Now using the above flipped functions, we can draw this by (there is a minor difference in metapost and diagrams. Metapost draws a circle of a given diameter while diagrams draws a circle of a given radius).
circle 50 `linewidth` 3 `linecolor` lightblue `fillcolor` lightgreen
Ah, much better than the metapost version.
I need to figure out two more things to be able to use the diagrams package in my publications.
- How to define the infix equivalents of metapost’s
- Write a Metapost/ConTeXt backend to render text using TeX.
Here is the complete code
import Graphics.Rendering.Diagrams linecolor = flip lineColor linewidth = flip lineWidth fillcolor = flip fillColor example1 = straight (pathFromVectors [(0,0),(100,-100)]) `linewidth` 4 `linecolor` red example2 = circle 50 `linewidth` 3 `linecolor` lightblue `fillcolor` lightgreen main = do renderAs PNG "line.png" (Width 100) example1 renderAs PNG "circle.png" (Width 100) example2