<?xml version="1.0" encoding="UTF-8"?><feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xml:lang="en"
  >
  <id>http://livingcode.org/feed/atom</id>
  <updated>2009-11-13T19:33:25Z</updated>
  <title type="text">Living Code</title>
  <subtitle type="text">Programming for the Fun of It</subtitle>
  <link rel="self" type="application/atom+xml" href="http://livingcode.org/feed" />
  <link rel="alternate" href="http://livingcode.org" />
  <rights type="text">Copyright 2009</rights>
  <generator uri="http://wordpress.org/" version="2.8.6">WordPress</generator>
      <entry>
    <id>http://livingcode.org/2008/drawing-hexmaps</id>
    <title type="html"><![CDATA[Drawing Hexmaps]]></title>
    <updated>2008-03-21T05:03:08Z</updated>
    <published>2008-03-21T05:03:08Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2008/03/20/drawing-hexmaps/feed" thr:count="3"  />
    <link rel="alternate" href="http://livingcode.org/2008/03/20/drawing-hexmaps" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[The other day, Thomas Guest talked about drawing chessboards, and ended with a challenge.  I wanted to answer a different challenge, however.  What if, instead of drawing on a rectangular grid, we wanted to draw on a hexagonal grid? The following is my slapdash answer.  For real-world use I&#8217;d make nice classes [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2008/03/20/drawing-hexmaps"><![CDATA[<p>The other day, Thomas Guest talked about <a href="http://wordaligned.org/articles/drawing-chessboards">drawing chessboards</a>, and ended with a challenge.  I wanted to answer a different challenge, however.  What if, instead of drawing on a rectangular grid, we wanted to draw on a hexagonal grid? The following is my slapdash answer.  For real-world use I&#8217;d make nice classes and pass more parameters to the methods, but to demonstrate the math I&#8217;m just going to use global constants and functions.</p>
<p>Like Thomas&#8217; article, I will show solutions using several different tools, in this case Apple&#8217;s <a href="http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_python/chapter_17_section_1.html#//apple_ref/doc/uid/TP30001066-CH218-TPXREF101">Core Graphics</a>, <a href="http://pygame.org/docs/">PyGame</a>, <a href="http://www.pythonware.com/library/pil/handbook/index.htm">Python Imaging Library</a> (PIL), and <a href="http://www.w3.org/TR/SVG11/">SVG</a>. All of these solutions will use the same constants and math:</p>
<p><code>
<pre>
# Constants used by each solution

from math import sin, cos, pi, sqrt
THETA = pi / 3.0 # Angle from one point to the next
HEXES_HIGH = 8 # How many rows of hexes
HEXES_WIDE = 5 # How many hexes in a row
RADIUS = 30 # Size of a hex
HALF_RADIUS = RADIUS / 2.0
HALF_HEX_HEIGHT = sqrt(RADIUS ** 2 - HALF_RADIUS ** 2)
IMAGE_WIDTH = int(RADIUS * (HEXES_WIDE * 3 + .5))
IMAGE_HEIGHT = int(HALF_HEX_HEIGHT * (HEXES_HIGH + 1))

# Functions (generators) used by each solution

def hex_points(x,y):
    '''Given x and y of the origin, return the six points around the origin of RADIUS distance'''
    for i in range(6):
        yield cos(THETA * i) * RADIUS + x, sin(THETA * i) * RADIUS + y

def hex_centres():
    for x in range(HEXES_WIDE):
        for y in range(HEXES_HIGH):
            yield (x * 3 + 1) * RADIUS + RADIUS * 1.5 * (y % 2), (y + 1) * HALF_HEX_HEIGHT
</pre>
<p></code></p>
<p>Now, given the above, what does the code look like to draw the hexes?  Because each library handles colours slightly differently, we will need a generator for colours (and we will need more than just black and white as the chessboard used, because each hex borders on six others).  I haven&#8217;t given a lot of thought to optimal colouring schemes: each colour generator simply produces red, yellow, blue, and green in a cycle.  Here is the image produced by the Core Graphics solution, followed by the code:</p>
<p><img src='http://livingcode.org/wp-content/uploads/2008/03/quartz_hexes.png' alt='Hex Image 1' /></p>
<p><code>
<pre>
def quartz_colours():
    while True:
        yield 1,0,0,1 # red
        yield 1,1,0,1 # yellow
        yield 0,0,1,1 # blue
        yield 0,1,0,1 # green

def quartz_hex():
    '''Requires a Mac with OS 10.4 or better and the Developer Tools installed'''
    import CoreGraphics as cg
    colours = quartz_colours()
    cs = cg.CGColorSpaceCreateDeviceRGB()
    c = cg.CGBitmapContextCreateWithColor(IMAGE_WIDTH, IMAGE_HEIGHT, cs, (0,0,0,.2))
    c.saveGState()
    c.setRGBStrokeColor(0,0,0,0)
    c.setLineWidth(0)
    for x,y in hex_centres():
        c.beginPath()
        c.setRGBFillColor(*colours.next())
        points = list(hex_points(x,y))
        c.moveToPoint(*points[-1])
        [c.addLineToPoint(*pt) for pt in points]
        c.drawPath(cg.kCGPathFill)
    c.restoreGState()
    c.writeToFile("quartz_hexes.png", cg.kCGImageFormatPNG)
</pre>
<p></code></p>
<p>Now for some cross-platform examples.  Here is the image generated by PyGame, followed by that code:</p>
<p><img src='http://livingcode.org/wp-content/uploads/2008/03/pygame_hexes.png' alt='Hex Image 2' /></p>
<p><code>
<pre>
def pygame_colours():
    while True:
        yield 255, 0, 0 # red
        yield 255, 255, 0 # yellow
        yield 0, 0, 255 # blue
        yield 0, 255, 0 # green

def pygame_hex():
    '''Requires PyGame 1.8 or better to save as PNG'''
    import pygame
    pygame.init()
    screen = pygame.display.set_mode((IMAGE_WIDTH, IMAGE_HEIGHT))
    colours = pygame_colours()
    for x,y in hex_centres():
        pygame.draw.polygon(screen, colours.next(), list(hex_points(x,y)))
    pygame.image.save(screen, 'pygame_hexes.png')
</pre>
<p></code></p>
<p>When you run the PyGame script, it will actually pop up a window very briefly, draw into the window, save the result, and close the window.  I also didn&#8217;t get the PyGame script to add transparency for the background, although I think it could be added fairly easily.  Now, for the web, here is a solution in SVG, with the image captured by screenshot in Safari, followed by the Python code, and the resulting SVG code:</p>
<p><img src='http://livingcode.org/wp-content/uploads/2008/03/picture-4.png' alt='Hex Image 3' /></p>
<p><code>
<pre>
def svg_colours():
    while True:
        yield 'rgb(255, 0, 0)'
        yield 'rgb(255, 255, 0)'
        yield 'rgb(0, 0, 255)'
        yield 'rgb(0, 255, 0)'

def svg_hex():
    out = open('svg_hexes.svg', 'w')
    print >> out, '''&lt;?xml version="1.0" standalone="no"?>
    &lt;!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    &lt;svg width="%spx" height="%spx" version="1.1" xmlns="http://www.w3.org/2000/svg">''' % (IMAGE_WIDTH, IMAGE_HEIGHT)
    colours = svg_colours()
    for pt in hex_centres():
        print >> out, '&lt;polygon fill="%s" stroke-width="0" points="%s" />' % (colours.next(),  ' '.join(["%s,%s" % (x,y) for (x,y) in hex_points(*pt)]))
    print >> out, '&lt;/svg>'
    out.close()
</pre>
<p></code></p>
<p>And here is the SVG created by the above script: <a href='http://livingcode.org/wp-content/uploads/2008/03/svg_hexes.svg' title='SVG Hexes'>SVG Hexes</a></p>
<p>Finally, one library which overlaps with the ones used by the Chessboard example: Python Imaging Library.</p>
<p><img src='http://livingcode.org/wp-content/uploads/2008/03/pil_hexes.png' alt='Hex Image 4' /></p>
<p><code>
<pre>
pil_colours = pygame_colours  # same format works, so we'll re-use it

def pil_hex():
    import Image, ImageDraw
    image = Image.new("RGBA", (IMAGE_WIDTH,IMAGE_HEIGHT), (0,0,0,0))
    colours = pil_colours()
    draw = ImageDraw.Draw(image)
    for x,y in hex_centres():
        draw.polygon(list(hex_points(x,y)), fill=colours.next())
    image.save('pil_hexes.png', 'PNG')
</pre>
<p></code></p>
<p>That&#8217;s it for my examples.  Thomas ended with a challenge for displaying chess, and for describing the position. To describe the position, I would use a standard chess notation, such as described <a href="http://www.xml.com/pub/a/2004/08/25/tourist.html">here</a>.  For my challenge, what other formats would be useful to create hex maps in?  POVRay?  Flash?  Any other examples out there?</p>
]]></content>
        </entry>
  </feed>
