Code Sketch

Spiral of hexagon tiles with flower pattern

By: Mike

// The plane can be tiled with a "honeycomb" of hexagons. The only other // regular polygons that can do so are squares and equilateral triangles // (and the latter only work if half of them are oriented "upside-down"). // // This script shows how the turtle can cover the plane with hexagonal tiles // by winding around an initial hexagon in a continuous spiral. A grid of // hexagons would be boring, so I've drawn a simple flower pattern (made from // squares) inside each tile. // // Why not design a more interesting pattern? Make your own pattern // a similar size to the hexagon, and remember when drawing a tile that // the turtle starts and ends at the bottom-left vertex, facing north! // (You can be more creative if you don't draw the hexagon outlines.) clear() // Length of the sides of the hexagons we're tiling val tileSide: Double = 50 // How many times should the spiral loop around the initial hexagon? val loops = 2 // How fast do you want the turtle to move? 1000 means normal speed, // 500 means double-speed, 10 means hundred times faster than normal // and use 0 if you want the turtle to draw instantly val speed = 400 // In your own tile pattern, remember to start and end in the bottom-left, // facing north, and all sides of the hexagon are tileSide long. def drawTile { penDown //only when drawing the tile patterns should the turtle pen be down // draw outline of hexagon setPenColor(red) left(30) //facing direction of bottom-left side repeat(6){ forward(tileSide) right(60) } // draw square pattern inside tile setPenColor(blue) repeat(6){ right() forward(tileSide) left() forward(tileSide) left() forward(tileSide) right(150) } right(30)//facing north again penUp //don't leave a line when moving to the next hexagon } // Each time the spiral winds around, it draws six sides ("arms") around // the existing tiles. To draw an arm we need to know how many tiles long // it should be. We will draw each tile, starting and finishing in the // bottom-left vertex of its hexagon, and move into position for the next tile. // Finally the turtle turns to face the direction of the next arm. // // To draw each tile consistently we must start and end facing north. So it's // helpful to know the orientation of each arm, measured by the angle the turtle // has to turn through to face north. def drawArm(tiles: Int, orientation: Double) { repeat(tiles) { left(orientation) // now facing north drawTile //starts and finishes in bottom-left of tile's hexagon right(orientation) //now facing in direction of arm again // Trigonometry tells us the turtle should move in the arm's direction // in a straight line of distance square root 3 times the tile side. // So we could use: forward(tileSide * 1.73205081) // But that path doesn't follow any of the sides of the hexagons in // our grid, so to show the grid more clearly let's get to the // bottom-left vertex of the next tile by traversing sides only. // For arms at a bearing of 0, 120 or 240 degrees the side most closely // matching the arm's direction is 30 degrees to the left, for the other // arms it is 30 degrees to the right. We can use division remainder: // orientation%120-30 is -30 or 30 for the two groups of arms. right(orientation%120-30) //align with nearest side forward(tileSide) //move to next vertex left(2*(orientation%120-30)) //align with next side forward(tileSide) //move to destination vertex right(orientation%120-30) //realign with arm direction } right(60) // arms wrap around clockwise, so turn right to start next arm } // We wind each loop of the spiral clockwise just by drawing its six arms. // Arms have different lengths, and orientations change by 60 degrees. // We use the the number of tiles in the shortest (first) arm to specify // how large to draw the loop. def windSpiral(shortArm: Int) { // Initial position is ready to start the tile immediately above the // lowest tile of the left side (which is in the 6th arm, so 1st arm is // unusually short). Continue north along the left side, finishing in // position to start the highest tile of the left side. (On the very first // loop this is just the initial position, so the arm has length 0). drawArm(shortArm, 0) // draw top tile of left side (bottom-left tile of upper-left side) // head on bearing of 060 degrees along upper-left side, finish in position // to start top tile drawArm(shortArm + 1, 60) // draw top tile then head on bearing of 120 degrees along upper-right side. // finish in position to start bottom-right tile of upper-right side. drawArm(shortArm + 1, 120) // draw top tile of right side (bottom-right of upper-right side) // head south along right side // finish in position to start bottom tile of right side drawArm(shortArm + 1, 180) //draw bottom tile of right side (top-right tile of lower-right side) //head on bearing of 240 degrees along lower-right side //finish in position to start the bottom tile drawArm(shortArm + 1, 240) // Draw bottom tile and head on bearing of 300 degrees along bottom-left // side, drawing all tiles on this side including the upper-left (the // bottom tile of left side) - hence this side is unusually long. // Finish in the bottom-left vertex of the tile to the upper-left of the // final tile drawn, facing north - this is the starting position for the // first arm of the next loop of the spiral. drawArm(shortArm + 2, 300) } //with all the definitions complete, let's start tiling! setAnimationDelay(speed) // speed up turtle penUp() // only when drawing the tiles should the pen be down drawTile // draw the initial tile, finish in bottom-left vertex facing north //move to what will become bottom-left vertex of hexagon to the upper-left of //the initial tile, and face north: in correct position and orientation for //the first (northbound) arm of the spiral. Note that in the first winding //around the initial hexagon, the northbound arm has length zero, so this tile //actually gets drawn as the first tile of the second arm! left(30) forward(tileSide) left(60) forward(tileSide) right() // Now wind the spiral around the initial hexagon! // with each winding, the size of the short arm increases by 1 for (i <- 0 to loops-1) { //as loops have shortest arms 0, 1, 2, etc windSpiral(i) }

**Your Comment:**