Skip to main content

The Ikea Lillabo Processing code

By popular demand... here's the code, written in Processing that actually draws the train sets. I hadn't released it because I didn't think it was very interesting, but you are welcome to it.
// --------------------------------------------------------------------------
//
// Small program to draw pictures of Ikea Lillabo track layouts using
// instructions derived from my Perl program.
//
// Written by John Graham-Cumming (http://www.jgc.org/)
//
// Released under the General Public License, version 2
//
// --------------------------------------------------------------------------

// This is the cursor position (x, y) coordinates and angle to the
// horizontal

float x, y, a;

// The length in pixels of a single straight piece

float len = 40;

// See the Perl program for a full explanation, but there are 8 curves
// in a circle and from that the radians of curve arc, the length of the
// straight line between the curve ends and the curve angle to the
// horizontal can be calculated.

float curves_in_circle = 8;
float radians_in_curve = 2 * PI / curves_in_circle;
float curve_angle = radians_in_curve / 2;
float curve_length = len * 2 * cos(PI/2 - radians_in_curve/2);

// The Processing equivalent of main()
void setup() {

// Set up the basic parameters for the drawing: a 1000x1000 canvas,
// with a white background. None of the elements drawn will be filled
// and the lines will be four pixels wide.

size(1000,1000);
background(255,255,255);
strokeWeight(4);
noFill();

// These are the nine possible layouts discovered by the Perl program
// and were copy/pasted here. Clearly this would be better done
// dynamically with this program reading the Perl program's output.

int layouts = 9;
String s[] = new String[layouts];

s[0] = "AAAACCAAAASSAAB";
s[1] = "CCCCCCSSAAAAAAB";
s[2] = "CAAAAACASSAAAAB";
s[3] = "CAAAAASCASAAAAB";
s[4] = "CAAAAASSCAAAAAB";
s[5] = "AAACAACAAASSAAB";
s[6] = "ACAAAASACSAAAAB";
s[7] = "ACAAAASSACAAAAB";
s[8] = "AACAAASSAACAAAB";

// (row, col) is the row and column position of the next layout to draw
// starting from the top left of the canvas. Since we know there are
// 9 the loop below lays them out 3x3. h is the height of space
// reserved for a layout.

int row = 0;
int col = 0;
int h = 250;
int w = h + 50;

for ( int j = 0; j < layouts; j++ ) {

// Start 200 pixels from the top left corner and with an initial
// angle of 0

a = 0;
x = 200 + w * col;
y = 200 + h * row;
col++;

if ( col == 3 ) {
col = 0;
row++;
}

for ( int i = 0; i < s[j].length(); i++ ) {
switch(s[j].charAt(i)) {
case 'B':
bridge();
break;

case 'C':
clockwise();
break;

case 'A':
anticlockwise();
break;

case 'S':
straight();
break;
}
}
}
}

// Function to draw a piece and update (x, y) and a
void draw_piece( float l, // Length of piece to be drawn
float ang ) // The angular change due to the piece
{
// If the ang is zero then this is a straight piece so use line(), if
// non-zero then it's a curve and so use arc()

if ( ang == 0 ) {

// (dx, dy) is the end of the piece truncated (the 0.8 multiplier)
// to leave a little gap between pieces.

float dx = x + l * 0.8 * cos(a + ang);
float dy = y + l * 0.8 * sin(a + ang);
line( x, y, dx, dy );
} else {
int h = (ang<0)?-1:1;

// (ox, oy) is the location of the centre of the circle on which the
// arc we are drawing lies. s and e are the starting and ending angles
// of arc to draw. Note that s must be less than e. Note the 1.5 here
// is used to shorten the arc to leave a small gap between pieces.

float ox = x - h * len * cos(PI/2-a);
float oy = y + h * len * sin(PI/2-a);
float s = a;
float e = a + ang * 1.5;
if ( s > e ) {
float t = e;
e = s;
s = t;
}

// The PI/2 adjustment here is needed because the angles in s and e are
// derived from a which is to the horizontal and the arc() function needs
// angles to the vertical

ellipseMode(CENTER);
arc( ox, oy, len*2, len*2, s - h * PI/2, e - h * PI/2 );
}

// Update (x,y) and a to be at the end of the new piece that's been
// added and with the correct orientation.

x += l * cos(a + ang);
y += l * sin(a + ang);
a += 2 * ang;
}

// Four functions to draw the four pieces giving them different colours.

void bridge()
{
stroke(255,0,0);
draw_piece(2*len,0);
}

void straight()
{
stroke(0,255,0);
draw_piece(len,0);
}

void clockwise()
{
stroke(255,0,255);
draw_piece(curve_length,curve_angle);
}

void anticlockwise()
{
stroke(0,0,255);
draw_piece(curve_length,-curve_angle);
}

Comments

Unknown said…
Thanks for posting the graphics code. I've been playing with both the generator and display code some today.

I was interested in the designs for two sets. I have it running with the second bridge as two straight sections. It's got about 1250 layouts generated so far. Some of them are not buildable due to stacked tracks. I'm thinking on how to check for this condition.

Popular posts from this blog

Your last name contains invalid characters

My last name is "Graham-Cumming". But here's a typical form response when I enter it:


Does the web site have any idea how rude it is to claim that my last name contains invalid characters? Clearly not. What they actually meant is: our web site will not accept that hyphen in your last name. But do they say that? No, of course not. They decide to shove in my face the claim that there's something wrong with my name.

There's nothing wrong with my name, just as there's nothing wrong with someone whose first name is Jean-Marie, or someone whose last name is O'Reilly.

What is wrong is that way this is being handled. If the system can't cope with non-letters and spaces it needs to say that. How about the following error message:

Our system is unable to process last names that contain non-letters, please replace them with spaces.

Don't blame me for having a last name that your system doesn't like, whose fault is that? Saying "Your last name …

Importing an existing SSL key/certificate pair into a Java keystore

I'm writing this blog post in case anyone else has to Google that. In Java 6 keytool has been improved so that it now becomes possible to import an existing key and certificate (say one you generated outside of the Java world) into a keystore.

You need: Java 6 and openssl.

1. Suppose you have a certificate and key in PEM format. The key is named host.key and the certificate host.crt.

2. The first step is to convert them into a single PKCS12 file using the command: openssl pkcs12 -export -in host.crt -inkey host.key > host.p12. You will be asked for various passwords (the password to access the key (if set) and then the password for the PKCS12 file being created).

3. Then import the PKCS12 file into a keystore using the command: keytool -importkeystore -srckeystore host.p12 -destkeystore host.jks -srcstoretype pkcs12. You now have a keystore named host.jks containing the certificate/key you need.

For the sake of completeness here's the output of a full session I performe…

More fun with toys: the Ikea LILLABO Train Set

As further proof of my unsuitability to be a child minder (see previous post) I found myself playing with an Ikea LILLABO 20-piece basic set train.


The train set has 16 pieces of track (12 curves, two straight pieces and a two part bridge) and 4 pieces of train. What I wondered was... how many possible looping train tracks can be made using all 16 pieces?

The answer is... 9. Here's a picture of the 9 different layouts.


The picture was generated using a little program written in Processing. The bridge is red, the straight pieces are green and the curves are blue or magenta depending on whether they are oriented clockwise or anticlockwise. The curved pieces can be oriented in either way.

To generate those layouts I wrote a small program which runs through all the possible layouts and determines which form a loop. The program eliminates duplicate layouts (such as those that are mirror images of each other).

It outputs a list of instructions for building loops. These instructions con…