## Wednesday, January 06, 2010

### 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 // horizontalfloat x, y, a;// The length in pixels of a single straight piecefloat 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 avoid 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);}

Labels:

If you enjoyed this blog post, you might enjoy my travel book for people interested in science and technology: The Geek Atlas. Signed copies of The Geek Atlas are available.

<$BlogCommentBody$>

<$BlogCommentDateTime$> <$BlogCommentDeleteIcon$>

<$BlogBacklinkControl$> <$BlogBacklinkTitle$> <$BlogBacklinkDeleteIcon$>
<$BlogBacklinkSnippet$>