The Signature Of Buses
Mr. Hartmut Warm, a programmer and engineer, analyzes periodic patterns in the movement of celestial bodies. What he gets is patterns of intricate beauty. He calls these patterns the “signature of spheres”, referring to Pythagoras’ “harmony of the spheres”. I recently came across a (German) documentary and thought this might be an interesting topic to investigate and learn F# on. Here I’m trying to analyze periodic patterns in the movements of bus lines of the city of Constance, calling the results the “signature of buses”.
First let me state that I do not want do deride Mr. Warm’s efforts or intentions. I find both his research and his results fascinating and aesthetically pleasing. What I want to find out is whether taking seemingly unrelated periodical movements like those of bus lines might lead to similar results as if regarding planets or moons. Any humorous allusions are purely coincidental ;-)
Reproducing the “signature of spheres”
The first step is to write a program to reproduce Mr. Warm’s results with regard to the movement of planets.
This picture shows the movement of Earth and Venus over time. The gray lines are the so called “link lines” that are drawn between the planets at each incremental step of their movements. The blue lines are “conjunction lines” that are drawn whenever a conjunction occurs, i. e. the planets have (approximately) the same angle. They connect the conjunction points sequentially. The frame center is the origin of both the cartesian and polar coordinate systems (body movement is being expressed in polar coordinates that are converted to cartesian and finally screen coordinates).
As we can see the result is very similar to what Mr. Warm has got (Fig. 2.2), but not exactly the same. I am using a simplified model for the planet movements; for example, I treat the orbitals as circles rather than ellipses. I am also using an iterative method to determine conjunction points which may introduce small errors. However, if you compare the pictures on Mr. Warm’s site (which I can’t include here for copyright reasons) you will recognize the similarity, especially the “flower pattern” in the middle and the rotating pentangle formed by the conjunction lines.
Here is my result for the link lines of Jupiter and Uranus (conjunctions are omitted):
This looks quite similar to Mr. Warm’s hexagonal pattern (Fig. 2.3). I have made the lines a little darker by increasing the alpha value of the brush.
Without worrying too much over the details I am now going to shamelessly assume that my program has achieved enough sophistication to calculate the “signatures” of the bus lines of Constance.
The bus lines of Constance
I started to study at the University of Constance in 1997. At that time I didn’t own a car so I was dependent on the buses of the Stadtwerke Konstanz, which are, in fact, a comfortable and reliable way to get around. There is an interactive route planner for you to get an overview.
Here’s a map with the route of line 1:
There are 14 bus lines altogether which is, incidentally, also the number of larger celestial bodies in our solar system ;-) Most of the lines stop at the railway station, so I’m taking the railway station as the center of my “omnibusal system” (the “sun”, so to speak) and treat the buses as bodies that revolve around this virtual center.
In my simulation bus movement is determined by a radius and a speed value in degrees. The speed value is the angular increment of the rotation during each step. For the “radius” of a bus line I choose the distance of the farthest bus stop to the railway station, expressed in kilometers. The relation of the angular movement of two buses therefore depends on their radius differences (according to Kepler’s third law the velocity is dependent on radius and mass of the central body only – for bodies much lighter than the central body, as is trivially the case for buses and the railway station).
Here’s a table with approximate values for some bus lines:
|Name||Distance mi||Distance km||Circumference in km|
I have now played around with various pairs of buses.
This is the result for lines 1 and 2:
Lines 3 and 2:
Lines 3 and 4:
Lines 2 and 4:
Lines 9 and 4:
As you can see the results are quite nice. We can recognize some interesting polygonal patterns with 4, 5, 7 and more edges.
Oops, I got it wrong!
I realized that the above pictures were the results of incorrect definitions: I mistakenly let the outer planet move faster than the inner ones. This violates Kepler’s law, but as the pictures are pretty I leave them in ;-) The source code now contains the correct definitions. As it turns out the new results are quite similar to those displayed above. If you want to see them yourself you can download the source code and try.
Using the code
The F# project is available for download. It should work with Visual Studio 2010 Express, though I haven’t tried. If you want to use the code you should pay attention to the following important settings at the beginning of the source:
- client_extent: Specifies the client coordinate range. This range should match the radiuses of the objects; i. e. if your largest radius is 9.0 you could set client_extent to (-10, –10, 10, 10). The origin (0, 0) should always be in the middle of the screen. Do not use asymmetric ranges.
- max_iterations: The most interesting things happen in the first few thousand iterations. After that the image tends to get blurry and performance suffers due to the many line objects. If you are only interested in the conjunction lines you can set it to 0 and comment out the call to draw_link_lines. As there are much fewer conjunction lines it will take some time until performance becomes significantly affected.
- step_interval: The most important parameter to affect the outcome of the patterns. It is used to scale the speed parameter in the object definitions. Larger intervals means faster movements. Interesting values are from about 1 to 10. The moving objects are defined by their name, the radius of the circle they describe, their speed in degrees per iteration and their shape; the shape also defines their color. They are always defined in pairs, as lists of the type busline.
To evaluate the pattern of a certain pair of objects you bind buslines to one of those lists. Make sure that you have set client_extent to a meaningful range and play with step_interval to get interesting patterns. You can also modify the bus line definitions to see what happens.
First experiences with F#
As this is my first F# program you may probably find some defects, so please be not too harsh with your critique. I expected to run into trouble but of course got stuck in totally unpredictable corners. Some more or less notable experiences:
- F# support in Visual Studio is not very sophisticated yet. I miss ReSharper very much, especially the ability to automatically reference DLLs that contain opened namespaces. Right now, I had to find out the DLL name on MSDN and reference it manually. Intellisense in F# seems to be a bit limited, too, though it can be really helpful if it works.
- F# Interactive didn’t help me at all. I expected use it more as I have seen in some tutorials, but its lack of multiline support made it difficult to use.
- Online references are a bit scarce. For example, figuring out how to use Form.Invoke to manipulate shape state on the UI thread was a major pain. Once you know how to do it, it’s easy, though. Of course there are hubFS, langref.org and fssnip.net, but these always seemed to contain only those examples that didn’t fit my current need ;-)
- As an imperative programmer, trying to write idiomatic F# (“functional style”) is quite a challenge. First I used a while loop with mutable variables (eek!) in one place but this looked ugly and cumbersome. When I finally got the hang of it I replaced it with a recursive loop and pattern matching which now looks really elegant and simple even to a novice like me.
- Having all the code in one source file makes me a little uncomfortable. For a project of this size it may do, but with a larger project I’d like to have the code a bit more structured. I’ll have to learn how to efficiently partition the code.
- Overall it was a pleasant experience working in F# and I’m looking forward to doing more in it!