Haskell, Vectors and Simple Mechanics – part 2.

Here we will continue the previous ideas about vectors and take a look at basic rendering of Vectors – for which we will use the Haskell Gloss package at https://hackage.haskell.org/package/gloss

Gloss claims that

“Gloss hides the pain of drawing simple vector graphics behind a nice data type and a few display functions. Gloss uses OpenGL under the hood, but you won’t need to worry about any of that. Get something cool on the screen in under 10 minutes.”

and to be fair I found it very easy to use but not without problems when installing. However I believe these problems are primarily macOS related and not due to issues with Gloss. I found that no matter what I did I could not get gloss to work from within ghci – it always gave this error

‘Dynamics.hs: user error (unknown GLUT entry glutInit)’

But using stack to run ghci is fine if in stack.yaml you add

ghc-options:
GLUT: -optl-Wl,-framework,GLUT

and then doing ‘stack ghci’ everything should be ok.

Using Gloss

At the core of Gloss is the Picture type.

and what’s really nice is that Picture is also a Monoid and so Picture can be combined and the result is also a Picture. This allows for a simple interface for rendering images.

Here’s a very simple program that will display x and y axes over a grey background in a large window.

We have a window located at (10,10) of size (1400, 800). Its background is greyish (0 would be black and 1 would be white). The axes are two lines, both red. Both ranging from +/- 10000. Notice that color red (line [ (-10000, 0), (10000, 0) ]) is of type Picture and so too is color red (line [ (0, -10000), (0, 10000) ]) and that they are combined with the Monoid mappend operator <> to give a composite Picture.

If we are to write a Haskell module to render our vectors using Gloss then some points to note:

  • We will need functions to convert a Vector into something that Gloss understands for rendering
  • Vectors are 3-D and Gloss is 2-D and so we will be ignoring the z component in Vector.
  • A Vector has a magnitude and a direction but no intrinsic notion of position. So when rendering we will either assume the location to be the origin or supply a position vector along with the vector to render.
  • To indicate the direction the rendering needs to include an arrow at the relevant end.

This function

takes a Vector v at position pv and creates a Line between the two points. Then, using the Monoid <> operator, combines the Line with an arrow head. The arrow head is provided by this function.

The arrowHead function is quite interesting and shows how using Vectors abstracts away much of the details of coordinates when dealing with points and lines in space. The polygonFromVectors function draws a filled in polygon using the list of Vectors as points in space. The arrowHead function takes the Vector v and ‘shifts’ it in such a way that the supplied position vector, pv, becomes the origin – i.e. v ^-^ pv. The function neg . normalise then ‘shrinks’ it to have a length of one unit and reverses it. So we have a unit vector in the opposite direction to the original. The lines

then give the ‘left’ and ‘right’ parts of the arrow and finally the three Vectors v, v ^+^ v', v ^+^ v'', which are the three points of the arrow head, are wrapped in a list and used by polygonFromVectors to actually do the drawing and fill in the arrow head. The function rotateXY is one I added to the Vectors module described in part 1. It’s just a 2-D rotation matrix expressed as a vector.

Here’s the whole Haskell module.

To try this out lets define a function to repeatedly draw a vector at the origin, rotate it and repeat.

This works by dividing the circle up into (2*pi / fromIntegral n) pieces and iterating the rotate function. i.e.
iterate (V.rotateXY (2*pi / fromIntegral n)).
We then create a Picture type from each Vector in the (lazily infinite) list of vectors using map lineVectorO. We then take however many we want from this list using take n and then call drawPics to render them. Simple, elegant and pleasing function composition.
Here’s some examples:

or this one showing more vectors

I think that’s enough for the moment and again all of this is available on Github. Next time we’ll look at some simple dynamics equations expressed in Vector form and look at visualising their solutions.

Thanks for reading!

 

7 comments

  • Aw, this was an incredibly good post. Taking the time and actual effort to make a top notch article… but what can I say… I put things off a lot and don’t seem to get anything done.

  • Hello there! This article couldn’t be written any better! Going through this article reminds me of my previous roommate! He continually kept preaching about this. I’ll send this information to him. Pretty sure he will have a very good read. I appreciate you for sharing!

  • Way cool! Some very valid points! I appreciate you writing this post and the rest of the website is also really good.

  • Hi would you mind sharing which blog platform you’re using? I’m going to start my own blog soon but I’m having a tough time making a decision between BlogEngine/Wordpress/B2evolution and Drupal. The reason I ask is because your layout seems different then most blogs and I’m looking for something completely unique. P.S My apologies for getting off-topic but I had to ask!

Leave a Reply

Your email address will not be published. Required fields are marked *

ˆ Back To Top