{"id":2554,"date":"2016-06-19T11:07:10","date_gmt":"2016-06-19T11:07:10","guid":{"rendered":"http:\/\/louisc.co.uk\/?p=2554"},"modified":"2016-11-05T11:17:47","modified_gmt":"2016-11-05T11:17:47","slug":"processing-drawing-a-hexagonal-grid","status":"publish","type":"post","link":"https:\/\/louisc.co.uk\/?p=2554","title":{"rendered":"Tinkering in Processing &#8211; Drawing a Hexagonal Grid"},"content":{"rendered":"<p>My friend Tine (Her cool Artwork <a href=\"http:\/\/www.tinebech.com\/\" target=\"_blank\">here<\/a>) has a new gig; an interactive swing set for display in the art exhibition at <a href=\"http:\/\/s2016.siggraph.org\/\" target=\"_blank\">SIGGRAPH 2016<\/a>, probably the largest\u00a0computer graphics and interactive techniques conference.\u00a0One of the reasons I feel Tine and I work so well together is we both appreciate the benefits of an iterative design process when molding technology to artistic ideas. Mess with ideas in the prototype stage, keep things as modular and flexible as possible and always plan for future expansion!<\/p>\n<p>So, I have never built an interactive computer visualization before, but i have dabbled with processing and have a rough idea of what will be involved.\u00a0From our initial brainstorming session we were keen\u00a0on a honeycomb grid structure which formed a good starting point for coding.<\/p>\n<p>This is a super quick processing animation made by randomly filling boxes to test the code described below:<\/p>\n<blockquote class=\"imgur-embed-pub\" lang=\"en\" data-id=\"uRirODL\"><p><a href=\"\/\/imgur.com\/uRirODL\">View post on imgur.com<\/a><\/p><\/blockquote>\n<p><script src=\"\/\/s.imgur.com\/min\/embed.js\" async=\"\" charset=\"utf-8\"><\/script><\/p>\n<h2>Drawing a Hexagon in Processing<\/h2>\n<p>Next was a trip down memory lane, some basic trig! The idea here is, in order to create a hexagon, we can calculate the position (x, y) of the 6 vertices which form the &#8220;pointy bits&#8221; in our 2D space then connect them together to form our shape.<\/p>\n<p>Starting from what we define as the center of the hexagon, the first known value we can calculate is the angle. Since processing works in radians rather than degrees, we will make our calculations as such. (For anybody reading who is not used to working in radians, the concept may seem alien but it is very straight forward, promise! Google for 10 mins, you&#8217;ll see!)<\/p>\n<p>We know a full circle forms and angle of 2? radians (360 degrees), so we simply divide this by 6 to calculate the angle our triangular calculation will form, essentially giving an angle of 2?\/6 (60 degrees). In code we can then cumulatively add this angle in a for loop until we reach all the way around the hexagon. In code this looks a little like this:<\/p>\n<div class=\"fusion-fullwidth fullwidth-box hundred-percent-fullwidth non-hundred-percent-height-scrolling\"  style='background-color: rgba(255,255,255,0);background-position: center center;background-repeat: no-repeat;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;'><div class=\"fusion-builder-row fusion-row \"><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nfloat centx = 50;\r\nfloat centy = 50;\r\nfloat radius = 40;\r\nfloat angle = TWO_PI \/ 6;\r\n\r\nbeginShape();\r\nfor (float a = PI\/6; a &lt; TWO_PI; a += angle) {\r\n float vx = centx + cos(a) * radius;\r\n float vy = centy + sin(a) * radius;\r\n vertex(vx, vy);\r\n }\r\nendShape(CLOSE);\r\n<\/pre>\n<p>This results in an output of:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-2595 alignnone\" src=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/hexagon.jpg\" alt=\"Hexagon Shape drawn with processing\" width=\"135\" height=\"157\" \/><\/p>\n<p>The beginShape() and endShape() commands result in the creation of a shape object from the set of vertices drawn within. By including the CLOSE command processing will draw the final line back to the first vertex closing the shape.<\/p>\n<h2>An Object Oriented Approach<\/h2>\n<p>Alright so we drew our hexagon with defined center points and radius, great! Now we need a grid of these, and better yet, since we plan to animate and gameify this grid we also need to store certain properties for each one.<\/p>\n<h3>A Hexagon Class<\/h3>\n<p>So, we have the code which draws a Hexagon along with the variables required to define its position and radius. For now the only additional property we will code in is a colour. So my initial draft for a class looks something like this:<\/p>\n<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nclass Hexagon {\r\n float centx;\r\n float centy;\r\n float radius;\r\n float angle = TWO_PI \/ 6;\r\n boolean fill = false;\r\n color c;\r\n \r\n\/\/Our Constructor takes the center coordinates along with a value for radius\r\n Hexagon( float x, float y, float r )\r\n {\r\n centx = x;\r\n centy = y;\r\n radius = r;\r\n }\r\n\r\n\/\/The draw function will define the fill values and calculate the coordinates\r\n void draw() {\r\n if(fill)\r\n fill(c);\r\n else\r\n noFill();\r\n \r\n beginShape();\r\n for (float a = PI\/6; a &lt; TWO_PI; a += angle) {\r\n float sx = centx + cos(a) * radius;\r\n float sy = centy + sin(a) * radius;\r\n vertex(sx, sy);\r\n }\r\n endShape(CLOSE);\r\n }\r\n\r\n\/\/The following are all simply utility functions for setting parameters\r\n float centx()\r\n {\r\n return centx;\r\n }\r\n\r\n float centy()\r\n {\r\n return centy;\r\n }\r\n\r\n color getColour()\r\n {\r\n return c;\r\n }\r\n \r\n void setFillColour(color col)\r\n {\r\n fill = true;\r\n c = col;\r\n }\r\n \r\n void setNoFill(boolean yesno)\r\n {\r\n fill = yesno;\r\n }\r\n}\r\n<\/pre>\n<p>A quick test of our new class:<\/p>\n<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/Lets define our array of hexagon objects globally\r\nHexagon[] hexagons;\r\n\r\nvoid setup()\r\n{\r\n size(640, 360, P3D);\r\n \/\/fullScreen(P2D);\r\n background(0);\r\n smooth();\r\n int radius=60;\r\n hexagons=new Hexagon[3];\r\n \/\/Manually define each new hexagon object's coordinates and radius\r\n hexagons[0] = new Hexagon(width\/4, height\/4, radius);\r\n hexagons[1] = new Hexagon(width\/2, height\/2, radius);\r\n hexagons[2] = new Hexagon(3*width\/4, 3*height\/4, radius);\r\n}\r\n\r\nvoid draw()\r\n{\r\n for( int i=0; i&lt;3; i++ )\r\n {\r\n hexagons[i].draw(); \/\/Cycle though our short array and call the draw function\r\n }\r\n}\r\n<\/pre>\n<p>Resulting in:<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-2603 alignnone\" src=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/hexagon_class-300x181.jpg\" alt=\"Hexagon Class in Processing\" width=\"300\" height=\"181\" srcset=\"https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/hexagon_class-200x121.jpg 200w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/hexagon_class-300x181.jpg 300w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/hexagon_class-400x241.jpg 400w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/hexagon_class-600x362.jpg 600w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/hexagon_class.jpg 646w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Great! We can now draw hexagons on demand!<\/p>\n<h1>Generating a Hexagonal Grid<\/h1>\n<p>In order to\u00a0easily reference each hexagon on our grid with a column and row style system we will generate a class simply named &#8220;HexGrid&#8221;. This will be responsible for drawing and storing the hexagon objects which form each cell, as well as allowing us to retrieve any given hexagon by provide a column and row number.<\/p>\n<p>First a simple bit of geometry math. In order to generate a grid of hexagons we must calculate the x and y offsets which allow them to fit together in the honeycomb style arrangement. First we need to decide on the standard orientation of our hexagons, as\u00a0<a href=\"http:\/\/www.redblobgames.com\/grids\/hexagons\/\" target=\"_blank\">this site<\/a>\u00a0suggests we can have &#8220;pointy&#8221; or &#8220;flat&#8221; topped grid.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-2607 alignnone\" src=\"http:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/Hex_Geometry-300x265.jpg\" alt=\"Hexagon Orientation\" width=\"300\" height=\"265\" srcset=\"https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/Hex_Geometry-200x177.jpg 200w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/Hex_Geometry-300x265.jpg 300w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/Hex_Geometry-400x354.jpg 400w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/Hex_Geometry-600x531.jpg 600w, https:\/\/louisc.co.uk\/wp-content\/uploads\/2016\/06\/Hex_Geometry.jpg 631w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>The height is easy to calculate, since the radius is measures to the points, the height is defined as twice the radius:<\/p>\n<p><img decoding=\"async\" class=\"mathtex-equation-editor\" src=\"http:\/\/chart.apis.google.com\/chart?cht=tx&amp;chl=height%3D2%5Ccdot%20radius\" alt=\"height=2\\cdot radius\" align=\"absmiddle\" \/><\/p>\n<p>The width of a hexagon is defined as:<\/p>\n<p><img decoding=\"async\" class=\"mathtex-equation-editor\" src=\"http:\/\/chart.apis.google.com\/chart?cht=tx&amp;chl=width%3D%5Cfrac%7B%20%5Csqrt%7B3%7D%20%7D%7B2%7D%20%5Ccdot%20height\" alt=\"width=\\frac{ \\sqrt{3} }{2} \\cdot height\" align=\"absmiddle\" \/><\/p>\n<p>which simply becomes:<\/p>\n<p><img decoding=\"async\" class=\"mathtex-equation-editor\" src=\"http:\/\/chart.apis.google.com\/chart?cht=tx&amp;chl=%5Cbigtriangleup%20X%20%3D%20width%20%3D%20%5Csqrt%7B3%7D%20%5Ccdot%20radius\" alt=\"\\bigtriangleup X = width = \\sqrt{3} \\cdot radius\" align=\"absmiddle\" \/><\/p>\n<p>Since horizontally each hexagon will be touching, this defines our x displacement. For the y displacement we will essentially be sitting the next row 3\/4 away from its previous row (with the start offset by 1\/2 a width) so that the &#8220;pointy&#8221; top fits within corresponding point left by the two meeting hexagons above. So finally giving:<\/p>\n<p><img decoding=\"async\" class=\"mathtex-equation-editor\" src=\"http:\/\/chart.apis.google.com\/chart?cht=tx&amp;chl=%5Cbigtriangleup%20Y%20%3D%20%5Cfrac%7B3%7D%7B4%7D%20%5Ccdot%20height%20%3D%20%5Cfrac%7B3%7D%7B2%7D%20%5Ccdot%20radius\" alt=\"\\bigtriangleup Y = \\frac{3}{4} \\cdot height = \\frac{3}{2} \\cdot radius\" align=\"absmiddle\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>(A great resource used for guidance in\u00a0deciding how to go about this was:\u00a0<a href=\"http:\/\/www.redblobgames.com\/grids\/hexagons\/\" target=\"_blank\">http:\/\/www.redblobgames.com\/grids\/hexagons\/<\/a>. There is some great analysis and live examples of the math, grid coordinate referencing and pseudo code implementations on hex grids!)<\/p>\n<p>Creating the grid is now a pretty straight forward task of two nested for loops, as such the final HexGrid class is shown below. I have added comments in the key areas:<\/p>\n<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nclass HexGrid {\r\n  Hexagon[][] grid; \/\/Our 2D storage array of Hexagon Objects\r\n  int cols, rows;\r\n  float radius;\r\n\r\n  \/\/Class Constructor required the grid size and cell radius\r\n  HexGrid(int nocol, int norow, int rad)\r\n  {\r\n    \/\/Define our grid parameters\r\n    cols = nocol;\r\n    rows = norow;\r\n    radius=float(rad);\r\n\r\n    \/\/2D Matrix of Hexagon Objects\r\n    grid=new Hexagon[cols][rows];\r\n\r\n    \/\/Lets assign the inital x,y coordinates outside the loop\r\n    int x = int(sqrt(3)*radius);\r\n    int y = int(radius);\r\n\r\n    \/\/These two nested for loops will cycle all the columns in each row\r\n    \/\/and calculate the coordinates for the hexagon cells, generating the\r\n    \/\/class object and storing it in the 2D array.\r\n    for( int i=0; i &lt; rows ; i++ ){\r\n      for( int j=0; j &lt; cols; j++)\r\n      {\r\n        grid[j][i] = new Hexagon(x, y, radius);\r\n        x+=radius*sqrt(3); \/\/Calculate the x offset for the next column\r\n      }\r\n      y+=(radius*3)\/2; \/\/Calculate the y offset for the next row\r\n      if((i+1)%2==0)\r\n        x=int(sqrt(3)*radius);\r\n      else\r\n        x=int(radius*sqrt(3)\/2);\r\n    }\r\n  }\r\n\r\n  \/\/This function will redraw the entire table by calling the draw on each\r\n  \/\/hexagonal cell object\r\n  void draw()\r\n  {\r\n    for( int i=0; i &lt; rows ; i++ ){\r\n      for( int j=0; j &lt; cols; j++)\r\n      {\r\n        grid[j][i].draw();\r\n      }\r\n    }\r\n  }\r\n\r\n  \/\/This function will return the hexagonal cell object given its column and row\r\n  Hexagon getHex(int col, int row)\r\n  {\r\n    return grid[col][row];\r\n  }\r\n\r\n}\r\n<\/pre>\n<p>Now we can have some fun by generating a grid and randomly filling it with colours \ud83d\ude42<br \/>\nHere is the code, once again comments should describe whats going on:<\/p>\n<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><div  class=\"fusion-layout-column fusion_builder_column fusion_builder_column_1_1  fusion-one-full fusion-column-first fusion-column-last fusion-column-no-min-height 1_1\"  style='margin-top:0px;margin-bottom:0px;'>\n\t\t\t\t\t<div class=\"fusion-column-wrapper\" style=\"background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;\"  data-bg-url=\"\">\n\t\t\t\t\t\t\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/* \r\nLouis Christodoulou - Hexagonal Grid Test\r\nMay 2016\r\n*\/\r\n\r\nHexGrid g;\r\ncolor[] mainpallet = {#F2385A, #4AD9D9};\r\nint rad, nwide, nhigh;\r\n\r\n\r\nvoid setup()\r\n{\r\n  size(1920, 1080);\r\n  smooth();\r\n  background(40);\r\n  \r\n  \/\/Define some of our grid parameters\r\n  rad=20;\r\n  nhigh = (height\/((rad*3)\/2));\r\n  nwide = int(width\/(sqrt(3)*rad))+1;\r\n  \r\n  \/\/Generate our grid object by calling the constructor\r\n  g = new HexGrid(nwide, nhigh, rad);\r\n  \/\/Draw our newly generated grid\r\n  g.draw();\r\n  \r\n  frameRate(60);\r\n}\r\n\r\nvoid draw()\r\n{\r\n  \/\/Since our grid cells now have a state, we can redraw our grid without loosing changes\r\n  g.draw();\r\n  \r\n  \/\/Each time draw loops we select 5 random hexagons in our grid and assign a\r\n  \/\/random colour from the pallet\r\n  for(int i=0; i &lt; 5 ; i++)\r\n  {\r\n    Hexagon selected = g.getHex(int(random(nwide)), int(random(nhigh)));\r\n    selected.setFillColour(mainpallet[int(random(2))]);\r\n  }\r\n}\r\n<\/pre>\n<h2><a href=\"http:\/\/louisc.co.uk\/PublicDownloads\/Code\/louisc_co_uk_hexagonClass.zip\">Download the final files here.<\/a><\/h2>\n<p>Thanks for reading and please do pop a comment below if you have questions, a better way of doing things, i have made a mistake or sharing your work which is similar!<div class=\"fusion-clearfix\"><\/div>\n\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>My friend Tine (Her cool Artwork here) has a new gig; an interactive swing set for display in the art exhibition at SIGGRAPH 2016, probably the largest\u00a0computer graphics and interactive techniques conference.\u00a0One of the reasons I feel Tine and I work so well together is we both appreciate the benefits of an iterative design process when molding technology to artistic ideas. Mess with ideas in the prototype stage, keep things as modular and flexible as possible and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2605,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[103,28,30],"tags":[105,104,109,110,106,107],"class_list":["post-2554","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kinetic-storyteller","category-projects","category-tinkering","tag-graphics","tag-interactive","tag-processing","tag-programming","tag-swing","tag-tine-bech"],"_links":{"self":[{"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2554","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2554"}],"version-history":[{"count":33,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2554\/revisions"}],"predecessor-version":[{"id":2717,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2554\/revisions\/2717"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=\/wp\/v2\/media\/2605"}],"wp:attachment":[{"href":"https:\/\/louisc.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2554"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2554"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/louisc.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2554"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}